Как автоматически обновлять поле в Django Admin (back end)
Представьте себе, что у меня есть модель Ticket:
class Ticket(models.Model):
name= models.CharField(max_length=30, verbose_name='name')
ticket_status = models.BooleanField(default=False, verbose_name='Is Active?')
ticket_end = models.DateField(blank=True, verbose_name='Closing Date', null=True)
class TicketAdmin(admin.ModelAdmin):
list_display= ('name','ticket_status','ticket_end ')
Я могу переопределить метод сохранения:
def save(self, *args, **kwargs):
if self.dep_end > ## Expiration date here ##:
self.dep_status = False
super(Ticket, self).save(*args, **kwargs)
И это работает в случае, когда я вручную обновляю объект. Но как реализовать автоматическое обновление в back end (в Django admin).
Что-то вроде этого: ticket_end = 1.02.2022, когда current date = 2.02.2022: update ticket_status = False.
from django.contrib import admin
class TicketAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
if self.model.dep_end > ## Expiration date here ##:
self.model.dep_status = False
super().save_model(request, obj, form, change)
Вы можете перезаписать save_model из ModelAdmin.
Не включайте поле ticket_status в вашу модель, если оно определяется ticket_end: вы можете сделать его свойством, или аннотировать так, чтобы у него было поле, которое True на случай, если срок действия билета еще не истек.
Таким образом, вы можете определить Ticket как:
from django.utils.timezone import now
class Ticket(models.Model):
name= models.CharField(max_length=30, verbose_name='name')
ticket_end = models.DateField(blank=True, verbose_name='Closing Date', null=True)
@property
def ticket_status(self):
return self.ticket_end is None or now() < self.ticket_end
или вы можете аннотировать Ticket с помощью:
from django.db.models import BooleanField, ExpressionWrapper, Q
from django.db.models.functions import Now
Ticket.objects.annotate(
_ticket_status=ExpressionWrapper(
Q(ticket_end=None) | Q(ticket_end__gt=Now()),
output_field=BooleanField()
)
)
вы можете использовать _ticket_status в предложении .filter(…), например,