如何在 Django 中每年重置自动递增编号

原文标题How to reset auto increment number every year in Django

我有一个模型IncomingCorrespondence带有自动递增字段ID。我也有字段number,我想为这个字段做两件事:

  1. 该字段将自动增加其值,就像 ID
  2. 每年新的一年,它的值将从 0(或 1)重新开始
ID Number Date
285 285 2020-03-12
286 286 2020-04-19
287 1 2021-01-01
class IncomingCorrespondence(models.Model):
   ID = models.models.AutoField(primary_key=True)
   date = models.DateField(null=True)
   number = models.IntegerField(null=True)

我怎样才能以最有效和最可靠的方式做到这一点?

原文链接:https://stackoverflow.com//questions/71909693/how-to-reset-auto-increment-number-every-year-in-django

回复

我来回复
  • Willem Van Onsem的头像
    Willem Van Onsem 评论

    您不需要存储数字,您可以简单地通过存储在数据库中的项目数来推导出它,因为它在那一年变成了:

    class IncomingCorrespondence(models.Model):
        date = models.DateField(null=True)
        created = models.DateTimeField(auto_now_add=True)
    
        @property
        def number(self):
            return IncomingCorrespondence._base_manager.filter(
                created__year=self.created.year,
                created__lt=self.created
            ).count() + 1

    因此,我们有一个时间戳created,它将存储对象创建的日期时间,我们计算时间戳前那一年的IncomingCorrespondence数加一。在这种情况下,您可以使用像django-softdelete[GitHub]这样的包来将已删除的对象保留在数据库中,并在查看项目时将其过滤掉。

    另一种方法可能是将最大值加一分配给字段:

    from django.db.models import Max
    from django.utils.timezone import now
    
    def next_number():
        data = IncomingCorrespondence._base_manager.filter(
            date__year=now().year
        ).aggregate(
            max_number=Max('number')
        )['max_number'] or 0
        return data + 1
    
    class IncomingCorrespondence(models.Model):
       ID = models.models.AutoField(primary_key=True)
       date = models.DateField(auto_now_add=True)
       number = models.IntegerField(default=next_number, editable=False)

    但这里 Django 将通过查询发送数字。如果有多个线程同时创建一个IncomingCorrespondence,那么这可能会失败。它还取决于插入时间,而不是IncomingCorrespondence对象的date

    1年前 0条评论
  • sudden_appearance的头像
    sudden_appearance 评论

    你应该用一些方法来统计number,比如查询今年创建的IncomingCorrespondence的数量。它不应该以任何其他方式完成(例如 cronjob),因为它不会稳定(crontab 可能会失败并且您最终会出现异常(甚至无法注意到),或者您将创建正确的实例在 crontab 重置序列之前)

    1年前 0条评论