【问题标题】:How do I make an auto increment integer field in Django?如何在 Django 中创建自动递增整数字段?
【发布时间】:2014-02-03 10:03:13
【问题描述】:

我正在为购物车制作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 自动递增?

【问题讨论】:

  • 默认会有一个自增id字段。
  • 使用pre_save信号检测购物车的变化?你的订单是什么?

标签: python django django-models


【解决方案1】:

在 Django 中

1 : Django 模型类具有名称为 id 的默认字段,即自动递增字段。
2:您可以使用@987654321@ 定义自己的自动增量字段 字段。

类订单(模型。模型): auto_increment_id = models.AutoField(primary_key=True) # primary_key = True 如果你不想使用 django 给你的模型的默认字段“id”

数据库设计

+------------+------------------------------------ -------------------------------------------------- -------------------------------------------------- ------------------------------------+ |表 |创建表 | +------------+------------------------------------ -------------------------------------------------- -------------------------------------------------- ------------------------------------+ |核心订单 |创建表`core_order`( `auto_increment_id` int(11) NOT NULL AUTO_INCREMENT, 主键(`auto_increment_id`) ) 引擎=InnoDB 默认字符集=latin1 | +------------+------------------------------------ -------------------------------------------------- -------------------------------------------------- ------------------------------------+ 一组中的 1 行(0.01 秒)

如果你想使用 django 的默认 id 作为增量字段。

类订单(模型。模型): add_date = models.DateTimeField(auto_now_add=True)

数据库设计

+--------------+------------------------------------ -------------------------------------------------- -------------------------------------------------- --------------------------+ |表 |创建表 | +--------------+------------------------------------ -------------------------------------------------- -------------------------------------------------- --------------------------+ |核心订单 |创建表`core_order`( `id` int(11) NOT NULL AUTO_INCREMENT, `add_date` 日期时间不为空, 主键(`id`) ) 引擎=InnoDB 默认字符集=latin1 | +--------------+------------------------------------ -------------------------------------------------- -------------------------------------------------- --------------------------+

【讨论】:

  • 整数字段需要这个。
  • 另外请注意,您不能拥有多个 AutoField,并且 Django 默认为 id 字段使用一个,因此如果您需要同时记录 id 和 不 表示主键的自动递增整数字段(例如,在用于保留数据插入顺序的Through 模型中),此解决方案不起作用。
  • AutoField 在每个模型多次使用时不起作用。我得到:A model can't have more than one AutoField
  • >AutoFields 必须设置 primary_key=True。
【解决方案2】:

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

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

您可以在Django Documentation for AutoField 中阅读有关 django 中 auto 字段的更多信息

【讨论】:

    【解决方案3】:
    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 Documentation for AutoField 了解与AutoField 相关的更多详细信息。

    【讨论】:

      【解决方案4】:

      您可以创建一个自动字段。这是相同的documentation

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

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

      【讨论】:

        【解决方案5】:

        已编辑:修复了在数据库中没有 YourModel 条目时停止工作的代码错误。

        很多地方都提到了应该如何使用 AutoField,当然,在可能的情况下应该使用它。

        但是,您自己实现自动递增字段是有正当理由的(例如,如果您需要一个从 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)
        

        【讨论】:

        • 我们如何在 YourModel 声明之前引用它?
        • @SubTain Malik 在这里是可能的,因为 YourModel 继承自 django 的 model.Model。在应用程序启动时,Django 首先加载模型类,使其能够工作
        【解决方案6】:

        我需要的东西:具有固定整数数量的文档编号,也可以像 AutoField 一样工作。

        我的搜索带我走遍了包括。这个页面。

        最后我做了这样的事情:

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

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

        max_length 可以根据需要为任何值(因此对应的default= 值)。

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

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

        随后将模型键字段更改为:

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

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

        到目前为止一切顺利。

        【讨论】:

        • 好吧,我认为一旦你重置你的索引,这将打破
        【解决方案7】:

        您可以覆盖 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

        【讨论】:

        • 我认为这行不通,它将始终为 1,我想您应该查询设置最后一个 order_number 并根据该数字递增它
        【解决方案8】:

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

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

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

        然后初始化,

        user = User(user_name="XYZ")
        

        如果按照以下方式初始化,

        user = User("XYZ")
        

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-03-08
          • 2017-02-08
          • 1970-01-01
          • 2015-03-05
          • 1970-01-01
          • 2017-06-01
          • 2012-04-12
          • 2020-07-18
          相关资源
          最近更新 更多