Django:做一个自定义的PK自动递增?

kxxlusnw  于 2023-01-18  发布在  Go
关注(0)|答案(5)|浏览(147)

我在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)
vd8tlhqk

vd8tlhqk1#

您可以对列id使用AutoField,而不是IntegerField。下面的代码应该适用于您:

id = models.AutoField(primary_key=True)

id现在将自动增加,并且不会出现在save方法中可能遇到的并发问题。

jpfvwuh4

jpfvwuh42#

我最终使用了非常相似的代码片段,但使其更通用一些:

def save(self, *args, **kwargs):
    if self.id is None:
        self.id =  self.__class__.objects.all().order_by("-id")[0].id + 1
    super(self.__class__, self).save(*args, **kwargs)

它使用self.__class__,所以你可以只复制粘贴这个代码到任何模型类,而不需要改变任何东西。

nkoocmlb

nkoocmlb3#

如何导入已有的值?在Transaction s __init__中写入一些内容来为您生成一个新的ID是很简单的,但是在不知道如何导入其他值的情况下,我不能肯定它是否会改变您使用它们的方式。

rks48beu

rks48beu4#

如果你删除你声明的id字段,django会自动假设:

id = models.AutoField(primary_key=True)

在Django 1.8中,inspectdb会自动检测auto_increment并在生成模型时使用AutoField

blpfk2vs

blpfk2vs5#

Django迁移将为您完成大部分的困难工作。
首先,停止对您的应用程序的任何访问,这样用户就无法在您使用数据库时对其进行更改。

作为预防措施,在执行任何工作之前备份数据库是非常明智的。

从www.example.com中删除手动声明的id字段models.py(即删除它)。
运行makemigrations,然后运行migrate,Django会根据您的数据库版本将id字段修改为正确的实现。
psql 中运行此(示例)命令,如有必要,可根据您的表名进行调整:

select setval(pg_get_serial_sequence('transactions_transaction', 'id'), max(id)) from transactions_transaction;

这将把你的id字段设置为你的表在postgres中正确的序列值(即你现有记录的id字段的最大值)。这是至关重要的,否则该值将为1!
就是这样从现在开始一切都将自动化。

相关问题