如何在 Django 中每年重置自动递增编号
python 202
原文标题 :How to reset auto increment number every year in Django
我有一个模型IncomingCorrespondence
带有自动递增字段ID
。我也有字段number
,我想为这个字段做两件事:
- 该字段将自动增加其值,就像 ID
- 每年新的一年,它的值将从 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)
我怎样才能以最有效和最可靠的方式做到这一点?
回复
我来回复-
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年前 -
sudden_appearance 评论
你应该用一些方法来统计
number
,比如查询今年创建的IncomingCorrespondence
的数量。它不应该以任何其他方式完成(例如 cronjob),因为它不会稳定(crontab 可能会失败并且您最终会出现异常(甚至无法注意到),或者您将创建正确的实例在 crontab 重置序列之前)1年前