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

u91tlkcl  于 2022-12-14  发布在  Go
关注(0)|答案(9)|浏览(390)

我正在为购物车创建一个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自动递增?

dm7nw8vv

dm7nw8vv1#

因 Django
1:Django模型类有默认字段id,是自动递增字段。
2:您可以使用AutoField字段定义自己的自动增量字段。

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

db设计

+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 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):
    add_date = models.DateTimeField(auto_now_add=True)

db设计

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

iqih9akk2#

在django中,每个模型的id字段默认为自动递增,但如果你手动使用自动递增,你只需要在你的模型AutoField中指定即可。

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

你可以在Django文档中阅读更多关于自动字段的信息

wr98u20j

wr98u20j3#

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),第二个表具有主键id(隐式)。
我认为没有必要直接使用这个;* 如果您不指定 *,主键字段将自动添加到您的模型中。否则,请查看Django文档中的AutoField以获取更多关于AutoField的详细信息。

q8l4jmvw

q8l4jmvw4#

编辑日期:修复了代码中的错误,即如果数据库中没有YourModel条目,则停止其工作。

有很多地方提到了应该如何使用自动域,当然,在可能的情况下应该使用它。
但是,您自己实现自动递增字段也是有正当理由的(例如,如果您需要一个从500开始的id,或者出于某种原因以十为单位递增)。
在您的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)
fiei3ece

fiei3ece5#

您可以创建一个自动字段。以下是
请记住Django不允许在一个模型中有多个自动字段,在您的模型中您已经有一个自动字段作为主键(默认设置),所以您必须覆盖模型的保存方法,并可能从表中获取最后插入的记录,相应地增加计数器并添加新记录。
请确保该代码是线程安全的,因为在多个请求的情况下,您可能最终会尝试为不同的新记录插入相同的值。

wkyowqbh

wkyowqbh6#

你可以重写Django保存方法官方文档中的相关内容。
代码的修改版本:

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.官方Django文档关于预保存

  1. stackoverflow example about using pre-save signal
ws51t4hk

ws51t4hk7#

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

我的搜索带我到处包括。这一页。

最后我做了这样的事:

我创建了一个表,其中DocuNumber字段为IntegerField,具有以下属性:

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

max_length值可以是所需的任何值(以及相应的default=值)。
创建上述模型时发出警告,我可以忽略。
然后,创建了一个文档(虚拟),如预期的那样,该文档的整数字段值为100000。
之后将型号关键字字段更改为:

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

创建的下一个(所需文档)的值为100001,后续数字递增1。
到目前为止一切顺利。

n3h0vuf2

n3h0vuf28#

您可以使用自动递增的默认主键(id)。
注意:当您使用第一个设计时,即使用默认字段(id)作为主键时,通过提及列名来初始化对象。

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

然后初始化,

user = User(user_name="XYZ")

如果您以下列方式初始化,

user = User("XYZ")

那么python将尝试设置id =“XYZ”,这将在数据类型上给予您错误。

eanckbw9

eanckbw99#

如果不打算将自动增量字段用作主键,则可以定义一个整型字段,并在保存()方法中更新此整型字段。

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)

    def save(self, *args, **kwargs):
        orders = Order.objects.all()

        if orders.exists() and self._state.adding:
            last_order = orders.latest('order')
            self.order = int(last_order.order) + 1
        super().save(*args, **kwargs)

如果我们不在这里使用self._state.adding,那么在更新过程中顺序也会自动增加,我们只查询self._state.adding,即我们想在创建过程中增加顺序。

相关问题