【问题标题】:Auto increment django model field per user每个用户自动增加 django 模型字段
【发布时间】:2016-02-28 14:14:48
【问题描述】:

我有这个模型:

class Invoice(models.Model):
    owner  = models.ForeignKey(settings.AUTH_USER_MODEL)
    data   = models.TextField(default=None, blank=True, null=True)
    number = models.PositiveIntegerField(default=0, null=False)

我需要为每个单独的用户自动增加字段number。理由是每个用户都有一个Invoice 列表,从number=1number=latest.number+1

我确实知道F() 表达式,但不知道如何为每个特定用户引用最新/最大的number。也许Invoice.objects.filter(owner=request.user).aggregate(Max('number')) 是路径,但我如何确保Max()F() 之间没有竞争条件?

【问题讨论】:

  • 您使用的是哪个数据库?
  • @Alasdair Postgres 9.4
  • @MTaqi 无论发票属于哪个用户,自动递增字段都会递增。我需要能够为所有用户拥有 Invoice.number=1。想想您自己的电信发票编号:它从 1 开始并递增,直到您致电取消每个客户的服务。
  • models.PositiveIntegerField(auto_increment_for('owner'))这样的东西会很好
  • 为什么没有日期字段,它会告诉您每个用户的最新发票。

标签: django django-models model field auto-increment


【解决方案1】:

您可以通过覆盖模型中的保存方法并将自定义逻辑写入其中来实现此功能和类似功能。

class Invoice(models.Model):
    owner  = models.ForeignKey(settings.AUTH_USER_MODEL)
    data   = models.TextField(default=None, blank=True, null=True)
    number = models.PositiveIntegerField(default=0, null=False)

    def save(self, *args, **kwargs):
        if self.pk:
            self.number += 1
        # Write all your logic here, like handeling max value etc
        return super(Invoice, self).save(*args, **kwargs)

【讨论】:

  • 好的,但这不会阻止竞争条件,当 2 个并发客户端尝试(几乎)同时保存时。这就是为什么我认为必须使用 F() 表达式来完成。这样增量操作是在数据库级别完成的。
  • 您可以处理 IntegrityError 并等待随机时间以避免竞争条件。参考:stackoverflow.com/a/3523439/1240938
  • 可能 F() 是更好的选择。我没用过。
  • 这里是您问题的最佳解决方案:查看最新保存的发票:stackoverflow.com/a/28199417/1240938
  • 这不是多线程应用程序的解决方案,也不是 cmets 中的任何一个选项。
【解决方案2】:

你可以像这样得到你的第一个或最后一个对象:

# For last Object
Model.objects.latest('field') # Field can be id or pk or ...

# For first Object
Model.objects.all().first() # You can also use it on filter

【讨论】:

    猜你喜欢
    • 2010-11-20
    • 2011-06-25
    • 2012-02-09
    • 2011-02-20
    • 2014-04-25
    • 2018-09-14
    • 2021-03-29
    • 2018-06-23
    • 2020-01-10
    相关资源
    最近更新 更多