Login

pre_save hook for checking state changes to models

Author:
FarmKing
Posted:
November 3, 2011
Language:
Python
Version:
1.3
Score:
0 (after 0 ratings)

Trying to build a state-machine that stores state in the model or in settings.py rather then in the database, I wrote this small generic pre_save hook that lets me leave all the data in the Model.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
class InvalidStateChange(Exception):                                                                                                                                                                      
    pass  

def check_state_changes(sender, instance, **kwargs):                                                                                                                                                      
    """                                                                                                                                                                                                   
    Compare the existing object in the database with the data about to be                                                                                                                                 
    saved.  If the state transition is invalid, abort the save.                                                                                                                                           
    """                                                                                                                                                                                                   
    if instance.id: # without an instance id, this is a create action                                                                                                                                            
        old = sender.objects.get(pk=instance.id)                                                                                                                                                          
        for state_dict in sender.VALID_STATE_CHANGES:                                                                                                                                                     
            if state_dict['from'] == old.state and instance.state == state_dict['to']:                                                                                                                    
                return True                                                                                                                                                                               
        raise InvalidStateChange(                                                                                                                                                                         
                "%s can't go from %s to %s" % (                                                                                                                                                           
                    sender.__name__,                                                                                                                                                                      
                    old.state,                                                                                                                                                                            
                    instance.state,                                                                                                                                                                       
                    )                                                                                                                                                                                     
                )                                                                                                                                                                                         
                                                                                                                                                                                                          
pre_save.connect(check_state_changes, Model)

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 6 months ago

Comments

FarmKing (on February 8, 2012):

even simpler with tuples instead of dictionaries

states = ((from_state, to_state),)

for from_state, to_state in sender.VALID_STATE_CHANGES: if from_state == old.state and to_state == instance.state: return True

#

Please login first before commenting.