Note that there are some explanatory texts on larger screens.

plurals
  1. PODjango model class decorator
    text
    copied!<p>I have a need to track changes on Django model instances. I'm aware of solutions like django-reversion but they are overkill for my cause.</p> <p>I had the idea to create a parameterized class decorator to fit this purpose. The arguments are the field names and a callback function. Here is the code I have at this time:</p> <pre><code>def audit_fields(fields, callback_fx): def __init__(self, *args, **kwargs): self.__old_init(*args, **kwargs) self.__old_state = self.__get_state_helper() def save(self, *args, **kwargs): new_state = self.__get_state_helper() for k,v in new_state.items(): if (self.__old_state[k] != v): callback_fx(self, k, self.__old_state[k], v) val = self.__old_save(*args, **kwargs) self.__old_state = self.__get_state_helper() return val def __get_state_helper(self): # make a list of field/values. state_dict = dict() for k,v in [(field.name, field.value_to_string(self)) for field in self._meta.fields if field.name in fields]: state_dict[k] = v return state_dict def fx(clazz): # Stash originals clazz.__old_init = clazz.__init__ clazz.__old_save = clazz.save # Override (and add helper) clazz.__init__ = __init__ clazz.__get_state_helper = __get_state_helper clazz.save = save return clazz return fx </code></pre> <p>And use it as follows (only relevant part):</p> <pre><code>@audit_fields(["status"], fx) class Order(models.Model): BASKET = "BASKET" OPEN = "OPEN" PAID = "PAID" SHIPPED = "SHIPPED" CANCELED = "CANCELED" ORDER_STATES = ( (BASKET, 'BASKET'), (OPEN, 'OPEN'), (PAID, 'PAID'), (SHIPPED, 'SHIPPED'), (CANCELED, 'CANCELED') ) status = models.CharField(max_length=16, choices=ORDER_STATES, default=BASKET) </code></pre> <p>And test on the Django shell with:</p> <pre><code>from store.models import Order o=Order() o.status=Order.OPEN o.save() </code></pre> <p>The error I receive then is:</p> <pre><code>TypeError: int() argument must be a string or a number, not 'Order' </code></pre> <p>The full stacktrace is here: <a href="https://gist.github.com/4020212" rel="nofollow">https://gist.github.com/4020212</a></p> <p>Thanks in advance and let me know if you would need more info!</p> <p><strong>EDIT:</strong> Question answered by randomhuman, code edited and usable as shown!</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload