简体   繁体   中英

How to automatically change model fields in django

I have a model and I want to know if it is possible to set a condition that triggers a change in the model field. For example, I have a model

class BillboardTracker(models.Model):
    client_name = models.CharField(max_length=400)
    entry_date = models.DateTimeField(default=datetime.now)
    duration = models.PositiveIntegerField()
    expiry_date = models.DateField()
    is_expired = models.BooleanField(default=False)

I want to know if it is possible to have a function in the model that makes is_expired equals to True when the expiry date is up. I tried this

def expire(self):
     if datetime.now == self.expiry_date:
        self.is_expired = True

but it's not working. Is it possible to implement this?

Use a @property

The simplest thing here is not to have an is expired field at all! It's not needed. What you need is a property.

class BillboardTracker(models.Model):
    client_name = models.CharField(max_length=400)
    entry_date = models.DateTimeField(default=datetime.now)
    duration = models.PositiveIntegerField()
    expiry_date = models.DateField()

    @property
    def is_expired(self):
        if datetime.now > self.expiry_date:
            return True
        return False

Remember, you don't have a field in a database, if that field is the same as another field with a simple calculation. This automatically eliminates your head ache of having to flag items as expired.

If you want to find out if an object has expired.

 if instance.is_expired == True:
    print 'yes, that ones gone'

Filtering

If you wanted to retrieve a whole set of objects that have expired

BillboardTracker.objects.filter(expiry_date__le=datetime.now())

This is why I mentioned that you don't need to store a field that can be easily calculated.

Index advantage

In most RDBMS a boolean field (such as your is_expired column) cannot be indexed effectively. So that actually means the above query will be faster than a query on that boolean field provided you create an index on the expiry_date field.

You need to make two changes in this function, Firstly use datetime.now() and secondly,

You might want to update your logic like this :

def expire(self):
     if datetime.now() >= self.expiry_date:
        self.is_expired = True
        return True
     else:
        return False

Because sometimes both the values might not be exactly same but still BillboardTracker need is_expired = True for all previous dates.

And in your views :

 def your_view(request):
    instance = BillboardTracker.objects.get(id=some_id)
    if instance.is_expired() == True:
        print 'expired'
    else:
        print 'fresh'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM