如何在 Django 中创建自动递增整数字段?
Posted
技术标签:
【中文标题】如何在 Django 中创建自动递增整数字段?【英文标题】:How do I make an auto increment integer field in 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
信号检测购物车的变化?你的订单是什么?
【参考方案1】:
在 Django 中
1 : Django 模型类具有名称为 id
的默认字段,即自动递增字段。
2:您可以使用@987654321@
定义自己的自动增量字段
字段。
数据库设计
+------------+------------------------------------ -------------------------------------------------- -------------------------------------------------- ------------------------------------+ |表 |创建表 | +------------+------------------------------------ -------------------------------------------------- -------------------------------------------------- ------------------------------------+ |核心订单 |创建表`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
和default
attributes
保留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.
另一种方法是使用信号。更多:
-
official Django docs about pre-save
*** 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" 这会给你的数据类型错误。
【讨论】:
以上是关于如何在 Django 中创建自动递增整数字段?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 PostgreSQL 在 DBeaver 中创建自动递增/SERIAL id 列?