pre_save hook for checking state changes to models

 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. State Machine inspired by acts_as_state_machine by santuri 5 years, 11 months ago
  2. SortableModel - abstract model class for sortable records by bendavis78 4 years, 10 months ago
  3. "Autoconnect" model decorator, easy pre_save and post_save signal connection by bendavis78 3 years, 9 months ago
  4. Choices class by dc 5 years, 5 months ago
  5. StateField by retro486 4 years, 9 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

#

(Forgotten your password?)