Как автоматически обновлять поле в 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(…), например,

Вернуться на верх