Как сбросить автоматическое увеличение числа каждый год в Django
У меня есть модель IncomingCorrespondence с полем ID с автоматическим инкрементом. У меня также есть поле number, и я хочу две вещи для этого поля:
- This field will auto-increment its value, just like
ID - Every new year its value will start over from 0 (or 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)
Как я могу сделать это наиболее эффективным и надежным способом?
Вам не нужно хранить это число, вы можете просто вывести его по количеству предметов, которые хранятся в базе данных с того момента, как исполнился этот год с:
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
We thus have a timestamp created that will store at what datetime the object was created, and we count the number of IncomingCorrespondence for that year before the timestamp plus one. You can in that case work with a package like django-softdelete [GitHub] to keep deleted objects in the database, and just filter these out when viewing the item.
Другим способом может быть присвоение полю максимального значения плюс единица:
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, то это может привести к сбою. Это также зависит от времени вставки , а не от date объекта IncomingCorrespondence.
Вы должны подсчитать number каким-либо методом, например, запросом количества созданных IncomingCorrespondence в этом году. Не следует делать это каким-либо другим способом (например, cronjob), поскольку он не будет стабильным (crontab может сбиться, и в итоге вы получите аномалии (и даже не сможете этого заметить), или вы создадите экземпляр прямо перед тем, как crontab сбросит последовательность)