When an object is exposed to the template context, its arguments-less methods are available. This is useful when these functions are "getters". But it can be hazardeous if these methods alter some data or have some side effects. Eventhough you likely trust the template writer, he may not be aware of a function's side effects or think call the wrong attribute by mistake.
Given the following model:
class Foobar(models.Model):
points_credit = models.IntegerField()
def credit_points(self, nb_points=1):
"""Credit points and return the new points credit value."""
self.points_credit = F('points_credit') + nb_points
self.save(update_fields=['points_credit'])
return self.points_credit
If you write this, by mistake, in a template:
You have {{ foobar.credit_points }} points!
This will increment the number of points each time the template is called. And you may not even notice it.
To prevent this, you must set the alters_data
attribute to True
to methods that have side effects. This will make it impossible to call them from a template.
def credit_points(self, nb_points=1):
"""Credit points and return the new points credit value."""
self.points_credit = F('points_credit') + nb_points
self.save(update_fields=['points_credit'])
return self.points_credit
credit_points.alters_data = True