Question

I have my models.py :

class Hotel(models.Model):
    name = models.CharField(max_length=20)
    currency = models.ForeignKey(Currency)


class Currency(models.Mode):
    code = models.CharField(max_length=3)
    name = models.CharField(max_length=10)

Whenever the currency field in hotel is changing I need to be able to do something. So I have a function like :

@receiver(pre_save,sender=Hotel)
def update_something(sender,**kwargs)
    obj = kwargs['instance']
    old_object = Hotel.objects.get(pk=obj.pk)
    '''
     Now I can do anything here comparing the oldo  object with the instance
    '''

The thing is I don't want to make a query for this, since then the purpose of signals becomes stupid and I become a fool.

So I should be able to do something like :

updated = kwargs['update_fields']
new_currency = updated['currency']

Is their a way I can find out that change for ONLY one particular field say currency ,instead of doing a query like this. I want to get the changes related to the currency foreign key and update things before I save.

Sorry for my bad English and not being able to use too technical terms.

Thanks :)

Was it helpful?

Solution

Rather hacky solution is to save object state on initialization.

from django.forms.models import model_to_dict

class Currency(models.Mode):
    code = models.CharField(max_length=3)
    name = models.CharField(max_length=10)

    def __init__(self):
        super(Currency, self).__init__()
        self.__state = model_to_dict(self)

    def updated(self):
        new_state = model_to_dict(self)
        return dict(set(self.__state.iteritems()) - set(new_state.iteritems()))

Method updated will return difference between initial and new states.

OTHER TIPS

The point of signals is better decoupling - allow other applications (that you don't necessarily know yet) to transparently hook into your application and/or avoid circular dependencies between application. There's really no point in using a signal here afaik (unless of course the signal handler is in another app and you don't want the app with the Hotel and Currency models to depend on this other app).

To answer your question: doing a query to retrieve the original state is the only way you can compare stored value and current value. Now if you're only interested in one specific field, you of course don't have to retrieve the whole model instance - just use queryset.values_list:

old_currency = Hotel.objects.filter(pk=obj.pk).values_list("currency", flat=True)[0]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top