我在Django中的一个模型中使用了custom primary keys(这是因为我在向数据库导入值时,它们已经附加了ID,因此保留现有值是有意义的)。
class Transaction(models.Model):
id = models.IntegerField(primary_key=True)
transaction_type = models.IntegerField(choices=TRANSACTION_TYPES)
date_added = models.DateTimeField(auto_now_add=True)
但是,现在我想向数据库中添加模型的新示例,并且想自动生成一个唯一的主键,但是如果我在创建示例时没有指定ID,我会得到一个错误:
t = Transaction(transaction_type=0)
t.save()
给出:
IntegrityError at /page
(1048, "Column 'id' cannot be null")
如何自动生成一个唯一的ID来指定新值,而不必改变导入现有值的方式?
- 更新**
我已经写了这个自定义方法,它似乎工作...
class Transaction(models.Model):
def save(self, *args, **kwargs):
if not self.id:
i = Transaction.objects.all().order_by('-id')[0]
self.id = i.id+1
super(Transaction, self).save(*args, **kwargs)
5条答案
按热度按时间vd8tlhqk1#
您可以对列
id
使用AutoField
,而不是IntegerField
。下面的代码应该适用于您:id
现在将自动增加,并且不会出现在save
方法中可能遇到的并发问题。jpfvwuh42#
我最终使用了非常相似的代码片段,但使其更通用一些:
它使用
self.__class__
,所以你可以只复制粘贴这个代码到任何模型类,而不需要改变任何东西。nkoocmlb3#
如何导入已有的值?在
Transaction
s__init__
中写入一些内容来为您生成一个新的ID是很简单的,但是在不知道如何导入其他值的情况下,我不能肯定它是否会改变您使用它们的方式。rks48beu4#
如果你删除你声明的id字段,django会自动假设:
在Django 1.8中,
inspectdb
会自动检测auto_increment
并在生成模型时使用AutoField
。blpfk2vs5#
Django迁移将为您完成大部分的困难工作。
首先,停止对您的应用程序的任何访问,这样用户就无法在您使用数据库时对其进行更改。
作为预防措施,在执行任何工作之前备份数据库是非常明智的。
从www.example.com中删除手动声明的
id
字段models.py(即删除它)。运行
makemigrations
,然后运行migrate
,Django会根据您的数据库版本将id字段修改为正确的实现。在 psql 中运行此(示例)命令,如有必要,可根据您的表名进行调整:
这将把你的
id
字段设置为你的表在postgres中正确的序列值(即你现有记录的id
字段的最大值)。这是至关重要的,否则该值将为1!就是这样从现在开始一切都将自动化。