【问题标题】:How to make the id auto increasing by 2 in the Model of Django?如何让 Django 模型中的 id 自动增加 2?
【发布时间】:2019-01-14 03:28:15
【问题描述】:

由于 MySQL 中的 auto_increment 设置是针对全局的,所以不能针对特定的表进行设置?

我正在考虑是否可以在 Django 的 Model 中让 id 自动增加 2?

models.py

class Video(models.Model):
    name = model.CharField(max_length=100, default='')
    upload_time = models.DateTimeField(blank=True, null=True)

    def __str__(self):
        return self.name

我该怎么办?感谢您的帮助。

【问题讨论】:

  • 您可以为每个真实对象插入一个“假”视频对象,然后将其删除。但即使那样你也不能保证,因为不同的数据库可以有特定的序列来分配 id。你为什么要这样做?为什么不简单地将id 与 2 相乘,以防您将其与外界通信?

标签: mysql django django-models


【解决方案1】:

您可以将模型的覆盖 save() 方法作为

from django.db.models import Max, F


class Video(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=100, default='')
    upload_time = models.DateTimeField(blank=True, null=True)

    def save(self, *args, **kwargs):
        if not self.pk:
            max = Video.objects.aggregate(max=Max(F('id')))['max']
            self.id = max + 2 if max else 1 # if the DB is empty
        super().save(*args, **kwargs)

    def __str__(self):
        return self.name

【讨论】:

    【解决方案2】:

    正确的方法是改变你的mysql服务器设置
    看看这个:auto_increment_increment

    【讨论】:

    • 它会影响数据库中的所有表,但我只想影响 Video 表...
    【解决方案3】:

    可能的解决方案:

    假设我有一个客户模型。

    Customer.objects.order_by('primay_key_id ').last().primay_key_id + 2)
    
    primay_key_id = models.IntegerField(default=(Customer.objects.order_by('primay_key_id ').last().primay_key_id + 2),primary_key=True)
    

    from django.db import transaction
    #Uncomment Lines for Django version less than 2.0
    def save(self): 
          "Get last value of Code and Number from database, and increment before save"
          #with transaction.atomic():
            #top = Customer.objects.select_for_update(nowait=True).order_by('-customer_customerid')[0] #Ensures Lock on Database
          top = Customer.objects.order_by('-id')[0]
          self.id = top.id + 1
          super(Customer, self).save()
    

    上述代码对于 Django 2.0 不会有并发问题:

    从 Django 2.0 开始,默认情况下相关行被锁定(不确定之前的行为是什么),并且可以使用 of 参数以与 select_related 相同的样式指定要锁定的行! 对于较低版本,您需要是原子的!

    from django.db import transaction
    def increment():
      with transaction.atomic():        
        ids = Customer.objects.all()
        length = len(ids)-1
        if(length<=0): #Changed to Handle empty Entries
         return 1
        else:
         id = ids[length].customer_customerid
         return id+2
    

    from django.db import transaction
    def increment():
      with transaction.atomic():        
        return Customer.objects.select_for_update(nowait=True).order_by('-customer_customerid')[0] #Ensures Atomic Approach!
    

    并将模型中的主键设置为整数字段,并在每个新条目上设置primary_key_field=increment() Like

    然后在你的 Models.py 中 将 Primary_Key 设置为:

    import increment()
    primay_key_id = models.IntegerField(default=increment(),primary_key=True)
    

    【讨论】:

    • 感谢,我添加了一行新代码来处理空表。请遵循该更改:)
    • 不要这样做。至少有三个主要问题:1)它受制于竞争条件; 2)它不考虑任何已删除的项目; 3)您在默认属性中调用函数而不是传递可调用对象,因此值将始终相同。
    • 嗯,这是一个解决方案,对于带有那个东西的单个表来说效果很好,我在我自己的 Django Rest API 中使用它,它确实工作得很好,你也可以覆盖保存方法这将消除大部分的东西!
    猜你喜欢
    • 1970-01-01
    • 2020-09-23
    • 2015-03-19
    • 2011-06-25
    • 1970-01-01
    • 2022-11-15
    • 2021-03-29
    • 2013-05-15
    • 2021-10-20
    相关资源
    最近更新 更多