'How to automatically update field in Django Admin (back end)

Imagine, that I have a model 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 ')

I can override save method:

def save(self, *args, **kwargs):
        if self.dep_end > ## Expiration date here ##:
            self.dep_status = False
        super(Ticket, self).save(*args, **kwargs)

And it's work in case when I am manually update object. But how realize automatically update in back end (in Django admin).

Something like this: ticket_end = 1.02.2022, when the current date = 2.02.2022: update ticket_status = False.



Solution 1:[1]

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)

You can overwrite save_model of ModelAdmin.

Solution 2:[2]

Don't include a ticket_status field in your model if it is determined by the ticket_end: you can make it a property, or annotate such that it has a field that is True in case the ticket did not expire yet.

You thus can define a Ticket as:

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

or you can annotate the Ticket with:

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()
    )
)

you can then use _ticket_status in a .filter(…) clause for example.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Willem Van Onsem