[英]Django - before model create
I have a model:我有一个 model:
book(book_id, release_year, book_number_by_release_year)
Field book_number_by_release_year
must be automatically generated and incremented by 1 within the release_year
field for new model instances.对于新的 model 实例,字段book_number_by_release_year
必须自动生成并在release_year
字段中递增 1。
What is the best way to do this in Django?在 Django 中执行此操作的最佳方法是什么? Thank you for your help谢谢您的帮助
from django docs you can create custom django-admin commands and if your operating system is unix based this command will automatically called when it's date is what you have set, looking form example in the docs above从 django 文档中,您可以创建自定义 django-admin 命令,如果您的操作系统是 unix,则当它的日期是您设置的日期时,该命令将自动调用,查看上面文档中的示例
from django.core.management.base import BaseCommand, CommandError
from polls.models import Question as Poll
class Command(BaseCommand):
help = 'Closes the specified poll for voting'
def add_arguments(self, parser):
parser.add_argument('poll_ids', nargs='+', type=int)
def handle(self, *args, **options):
for poll_id in options['poll_ids']:
try:
poll = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise CommandError('Poll "%s" does not exist' % poll_id)
# you can type your logic here
poll.opened = False
poll.save()
self.stdout.write(self.style.SUCCESS('Successfully closed poll "%s"' % poll_id))
this will automatically close the polls that is created by user这将自动关闭用户创建的投票
for your case对于你的情况
def handle(self, *args, **options):
.
.
# you can type your logic here
if (datetime.date.today() - self.release_year) == 0:
self.book_number_by_release_year +=1
self.save()
consider adding your attempts and models.py for more detailed answer and for good question check this question for more details考虑添加您的尝试和 models.py 以获得更详细的答案,对于好的问题,请查看此问题以获取更多详细信息
You can use pre_save
signal, or override the save
method.您可以使用pre_save
信号,或覆盖save
方法。 I prefer the former as we're not changing methods defined by django
.我更喜欢前者,因为我们不会更改django
定义的方法。 Here is a rough implementation on using pre_save
signal:这是使用pre_save
信号的粗略实现:
from django.db.models.signals import pre_save
from django.db.models import Max
from django.db import models
class Book(models.Model):
book_id = models.IntegerField()
release_year = models.IntegerField()
book_number_by_release_year = models.IntegerField()
@receiver(pre_save, sender=Book)
def populate_book_number_by_release_year(sender, instance, *args, **kwargs):
# fetch the last book_id given
args = Book.objects.filter(release_year=instance.release_year)
max_value = args.aggregate(Max('book_number_by_release_year'))
if max_value == None:
instance.book_number_by_release_year=0
else:
instance.book_number_by_release_year=max_value['book_number_by_release_year']
PS: Do note that there's a race condition possibility, like any other autoincrement
function. PS:请注意存在竞争条件的可能性,就像任何其他autoincrement
function 一样。
Documentation: https://docs.djangoproject.com/en/4.1/ref/signals/文档: https://docs.djangoproject.com/en/4.1/ref/signals/
We can try using AutoField
for the above use case.对于上述用例,我们可以尝试使用AutoField
。 Instead of relying on a pre_save
signal, we can make our changes at model definition like so:我们可以在 model 定义中进行更改,而不是依赖pre_save
信号,如下所示:
class Book(models.Model):
book_id = models.IntegerField()
release_year = models.IntegerField()
book_number_by_release_year = models.AutoField(primary_key=False)
Link to the official documentation: https://docs.djangoproject.com/en/4.0/ref/models/fields/#autofield官方文档链接: https://docs.djangoproject.com/en/4.0/ref/models/fields/#autofield
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.