Django Max函数未返回最大值

时间:2015-07-17 11:55:10

标签: python django postgresql

我需要数据库中特定字段的最大值,将其递增1并成为我的新订单号。

我这样做的方式是:

def generate_order_number(self):
    q_number = Order.objects.all().aggregate(Max('number'))['number__max']
    if q_number:
        q_number += 1
    else:
        q_number = 1

    return q_number

此代码在订单号10之前完全正常。但是,当尝试订单号11时,aggregate查询将最大值返回为9,因此,该函数返回10作为新订单号 - 这不符合整个过程(数据库中的数字为unique)。

为什么会这样?

我正在使用Django / PostgreSQL组合。我number的数据库条目是:

number = models.BigIntegerField(
    _("Quotation number"), db_index=True, unique=True)

此外,当我尝试直接操作数据库中的订单号时,我得到的错误是:

ProgrammingError at /admin/order/order/21/
operator does not exist: character varying = integer
LINE 1: ..._order" WHERE ("order_order"."number" = 11 AND N...
                                                         ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

PostgreSQL serial数据类型在内部创建smallint / int / bigint列和序列。有效地使其等效于普通的int列,默认设置为某个序列。

例如,这个:

CREATE TABLE tablename (
    colname SERIAL
);

内部产生了这个:

CREATE SEQUENCE tablename_colname_seq;
CREATE TABLE tablename (
    colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;

这是你的问题所在,而普通的CREATE SEQUENCE只是增加了一个简单的序列,它递增一个,永远不会下降。使用setval,您可以重置序列当前值以重用旧数字。

请注意,这可能会导致重复键约束,因为主键仍然是唯一的,因此如果您确实获得了重复的键约束,只需将序列重置为尚未使用的范围(SELECT MAX(colname)+1 FROM tablename应该给你一个正确的起点。)