如何在Django中创建一个自动增量整数字段?

时间:2014-01-15 04:01:51

标签: python django django-models

我正在为购物车制作Order模型,我需要创建一个在订单生成时自动递增的字段:

class Order(models.Model):
    cart = models.ForeignKey(Cart)
    add_date = models.DateTimeField(auto_now_add=True)
    order_number = models.IntegerField()
    enable = models.BooleanField(default=True)

如何进行IntegerField自动增量?

8 个答案:

答案 0 :(得分:61)

在Django 1:将有一个名为“id”的默认字段,它是自动增量 2:您可以使用AutoField将任何字段定义为自动增量字段 领域。

class Order(models.Model):
    auto_increment_id = models.AutoField(primary_key=True)
    #you use primary_key = True if you do not want to use default field "id" given by django to your model

db design

+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table      | Create Table                                                                                                                                                  |
+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| core_order | CREATE TABLE `core_order` (
  `auto_increment_id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`auto_increment_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

如果要将django的默认ID用作增量字段。

class Order(models.Model):
    dd_date = models.DateTimeField(auto_now_add=True)

db design

+-------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table       | Create Table                                                                                                                                                    |
+-------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| core_order | CREATE TABLE `core_order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `dd_date` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+-------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+

答案 1 :(得分:16)

在每个模型的django中,您将获得默认的id字段,即自动增量。但是如果你手动想要使用自动增量仍然。您只需在模型AutoField中指定。

class Author(models.Model):
    author_id = models.AutoField(primary_key=True)

您可以在Django Documentation for AutoField

中详细了解django中的自动字段

答案 2 :(得分:8)

<componentElement>
    <reportElement key="table" style="table" x="0" y="33" width="360" height="50" uuid="6a7d5ab9-f15d-4676-85b2-1e48f016c155"/>
    <jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
        <datasetRun subDataset="tableData" uuid="fa5df3de-f4c5-4bfc-8274-bd064e8b81e6">
            <connectionExpression><![CDATA[$P{REPORT_CONNECTION}]]></connectionExpression>
        </datasetRun>
        <jr:columnGroup width="217" uuid="c96f6ab0-8cce-4dc7-b686-da6928e7cabb">
            <jr:tableHeader height="61" rowSpan="1">
                <textField>
                    <reportElement x="0" y="0" width="217" height="61" uuid="98aa260d-7e84-4df7-89cc-fc1eabdcf656"/>
                    <textElement textAlignment="Center" verticalAlignment="Middle"/>
                    <textFieldExpression><![CDATA["MY TABLE LABEL"]]></textFieldExpression>
                </textField>
            </jr:tableHeader>
            <jr:column width="90" uuid="889a828a-ad48-40a0-81f4-326a95d6585c">
                <jr:columnHeader style="table_CH" height="60" rowSpan="1"/>
                <jr:detailCell style="table_TD" height="43" rowSpan="1">
                    <textField>
                        <reportElement x="0" y="0" width="90" height="43" uuid="82b2a835-4373-4638-b75a-d43f531678ba"/>
                        <textFieldExpression><![CDATA[$F{myField1}]]></textFieldExpression>
                    </textField>
                </jr:detailCell>
            </jr:column>
            <jr:column width="127" uuid="004c3afe-c39f-44e2-a82d-5c96697ebd7e">
                <jr:columnHeader style="table_CH" height="60" rowSpan="1"/>
                <jr:detailCell style="table_TD" height="43" rowSpan="1">
                    <textField>
                        <reportElement x="0" y="0" width="90" height="43" uuid="90287319-765f-49a0-9f80-0851f40f2b13"/>
                        <textFieldExpression><![CDATA[$F{myField2}]]></textFieldExpression>
                    </textField>
                </jr:detailCell>
            </jr:column>
        </jr:columnGroup>
    </jr:table>
</componentElement>

********或*******

class Belly(models.Model):
    belly_id = models.AutoField(primary_key=True)
    belly_name = models.CharField(max_length=50)

区别在于:

第一个表包含主键class Belly(models.Model): belly_name = models.CharField(max_length=50) (指定为belly_id),第二个表包含主键AutoField(隐式)。

我认为不需要直接使用它;如果您未指定,主键字段将自动添加到您的模型中。除此以外 查看Django Documentation for AutoField以获取与id

相关的更多详细信息

答案 3 :(得分:5)

您可以创建自动对象。以下是同一

documentation

请记住,Django不允许在模型中拥有多个AutoField,在您的模型中,您已经有一个用于主键(默认情况下)。因此,您必须覆盖模型的保存方法,并且可能会从表中获取最后插入的记录,并相应地增加计数器并添加新记录。

请确保代码线程安全,因为如果有多个请求,您可能最终会尝试为不同的新记录插入相同的值。

答案 4 :(得分:5)

已编辑:修复了代码错误,如果数据库中没有YourModel条目,则会导致代码停止工作。

关于如何使用自动字段,有很多提及,当然,在可能的情况下,您应该使用它。

但是,出于正当理由,您自己可以实现自动递增字段(例如,出于某种原因,如果您需要一个ID从500开始或以几十为单位递增计数)。

在您的models.py

from django.db import models

def from_500():
    '''
    Returns the next default value for the `ones` field,
    starts from 500
    '''
    # Retrieve a list of `YourModel` instances, sort them by
    # the `ones` field and get the largest entry
    largest = YourModel.objects.all().order_by('ones').last()
    if not largest:
        # largest is `None` if `YourModel` has no instances
        # in which case we return the start value of 500
        return 500
    # If an instance of `YourModel` is returned, we get it's
    # `ones` attribute and increment it by 1
    return largest.ones + 1

def add_ten():
    ''' Returns the next default value for the `tens` field'''
    # Retrieve a list of `YourModel` instances, sort them by
    # the `tens` field and get the largest entry
    largest = YourModel.objects.all().order_by('tens').last()
    if not largest:
        # largest is `None` if `YourModel` has no instances
        # in which case we return the start value of 10
        return 10
    # If an instance of `YourModel` is returned, we get it's
    # `tens` attribute and increment it by 10
    return largest.tens + 10


class YourModel(model.Model):
    ones = models.IntegerField(primary_key=True,
                               default=from_500)
    tens = models.IntegerField(default=add_ten)

答案 5 :(得分:1)

您可以使用自动增量的默认主键(id)。

注意:当您使用第一个设计,即使用默认字段(id)作为主键时,通过提及列名来初始化对象。 e.g。

class User(models.Model):
    user_name = models.CharField(max_length = 100)

然后初始化,

user = User(user_name="XYZ")

如果按以下方式初始化,

user = User("XYZ")

然后python会尝试设置id =“XYZ”,这会给你数据类型的错误。

答案 6 :(得分:1)

我需要的:具有固定整数值的文档编号,其作用也类似于AutoField

我的搜索将我带入了整个范围。此页面。

最后,我做了这样的事情:

我创建了一个带有DocuNumber字段的表,作为带有foll的IntegerField。属性:

  • max_length=6
  • primary_key=True
  • unique=True
  • default=100000

max_length会根据需要提供任何值(并因此具有相应的default=值)。

在创建上述模型时会发出警告,我可以忽略。

然后,按预期方式创建一个文档(虚拟),该文档的整数字段值为100000。

然后将模型关键字字段更改为:

  • 将字段类型更改为:AutoField
  • 摆脱了max_lengthdefault属性
  • 保留了primary_key = True属性

下一个创建的(所需文档)的值为100001,其后的数字加1。

到目前为止很好。

答案 7 :(得分:0)

您可以覆盖Django保存方法official doc about it

代码的修改版本:

class Order(models.Model):
    cart = models.ForeignKey(Cart)
    add_date = models.DateTimeField(auto_now_add=True)
    order_number = models.IntegerField(default=0)  # changed here
    enable = models.BooleanField(default=True)

    def save(self, *args, **kwargs):
        self.order_number = self.order_number + 1
        super().save(*args, **kwargs)  # Call the "real" save() method.

另一种方法是使用信号。更多一:

  1. official Django docs about pre-save
  2. stackoverflow example about using pre-save signal