Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I update a Django models.DateTimeField when another, specific field in the same model is updated?

I have two fields in a model here:

is_active = models.BooleanField(default=False)
active_from = models.DateTimeField(blank=True)

When is_active is set to True, I'd like active_from to be updated to the current datetime.

How do I go about doing this? I'm open to alternatives if there's a cleaner way of doing this with one field as well.

Thanks!

EDIT: I'd like to contain this within the model to keep things encapsulated. This will be part of an API.

like image 670
StringsOnFire Avatar asked Jun 16 '16 19:06

StringsOnFire


People also ask

How do you add a new field to a model with new Django migrations?

To answer your question, with the new migration introduced in Django 1.7, in order to add a new field to a model you can simply add that field to your model and initialize migrations with ./manage.py makemigrations and then run ./manage.py migrate and the new field will be added to your DB. Save this answer.

How do I override a Django model?

Whenever one tries to create an instance of a model either from admin interface or django shell, save() function is run. We can override save function before storing the data in the database to apply some constraint or fill some ready only fields like SlugField.

How do you create an instance of a model from another model in Django?

To create a new instance of a model, instantiate it like any other Python class: class Model (**kwargs) The keyword arguments are the names of the fields you've defined on your model. Note that instantiating a model in no way touches your database; for that, you need to save() .


3 Answers

One way to do it is to define a save() method on your custom model looking for change in is_active. There is no easy way to achieve this: you need to manually save the previous state of the value of is_active by defining a custom __init__-method. It could look something like this:

class MyModel(models.Model):
    is_active = models.BooleanField(default=False)
    active_from = models.DateTimeField(blank=True)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.__is_active = self.active

    def save(self, *args, **kwargs):
        if self.is_active and not self.__is_active:
            self.active_from = datetime.now()
        super().save(*args, **kwargs)

This question has some answers which might help.

like image 139
Jieter Avatar answered Oct 17 '22 18:10

Jieter


Another alternative is the FieldTracker from django-model-utils. I'm going to be using this moving forwards, as it makes more complex manipulation easier during save().

like image 22
StringsOnFire Avatar answered Oct 17 '22 17:10

StringsOnFire


When you toggle is_active update active_from at the same time.

for example:

def toggle_user_active_and_update(request, *a, **kw):
    request.user.is_active = !request.user.is_active
    request.user.active_from = datetime.datetime.now()
    request.user.save()
like image 1
marcusshep Avatar answered Oct 17 '22 16:10

marcusshep