How can I make a variable derived from a model class instance change as soon as another instance is created in Django?

StackOverflow https://stackoverflow.com/questions/22234921

  •  10-06-2023
  •  | 
  •  

Question

In my models.py I have a model class ExchangeRate the most current of which I have used to derive a variable called rate. Then I declared a function that uses this variable to generate the corresponding value of GBP to Euro.

The function is used by one of my views to update context variables.

This works great, but when I create a new instance of ExchangeRate which should become the most recent, I find that there is a persistence of the former value even when I leave the url of interest. I can only get the new value to be used when I stopped and restarted the development server.

How can I make the exchange rate change along with the creation of a new instance of ExchangeRate when I leave and then return to the relevant page/url, or maybe at every refresh of the browser?

I suspect that this has something to do with session storage which I need (don't want to turn it off assuming that's the problem).

More details are below:

*models.py

class ExchangeRate(models.Model):
    value = models.DecimalField(max_digits=5, decimal_places=2)
    date = models.DateTimeField(auto_now=True)

    def __unicode__(self):
        return str(self.value)

I assigned it like so just below the class -

rate = ExchangeRate.objects.latest('date').value

and used it in the following function-

def euro_total(amount):
    return int(rate * amount)

*views.py.

The output was used to populate the context of the following SessionWizardView

class PaymentWizard(SessionWizardView):
    def get_context_data(self, form, **kwargs):
        context = super(PaymentWizard, self).get_context_data(form=form, **kwargs)
        cleaned_data = super(PaymentWizard, self).get_cleaned_data_for_step('amount') or {'method': 'none'}
        payment_choice = cleaned_data.get('payment_choice')
        if cleaned_data.get('amount'):
            amount = int(cleaned_data.get('amount'))
            if self.steps.current == 'confirm_amount' or 'bank' or 'card' and not None:
                updates =({'input_amount': amount},
                {'payment_choice': payment_choice},           
                {'GBP_total': gbp_total(amount, payment_choice)},
                {'EURO_total': euro_total(amount)},
                )
            for update in updates:
                context.update(update)
    return context

Thanks everyone.

Was it helpful?

Solution

So, your final comment has revealed the problem. Anything defined at global level will be executed when the module is first imported, and not change until the server process is restarted.

You'll need to move that line somewhere it is executed every time: for instance, inside the euro_total function.

Alternatively, if you're worried about hitting the db each time, you could use something like memcache, with a shortish timeout, and get your function to check the cache first before loading from the database.

Or, you could perhaps add a post-save signal to ExchangeRate, which explicitly sets the global rate variable when the a new value is added to the db.

OTHER TIPS

If rate needs to be a global level item (maybe you're using it as a cached value?) then as @Daniel says, you can use a post-save signal to refresh it automatically whenever a new ExchangeRate object is saved.

See django.db.models.signals.post_save and how to use signals

in the Django documentation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top