Package pyperry :: Package middlewares :: Module model_bridge
[frames] | no frames]

Source Code for Module pyperry.middlewares.model_bridge

  1  from pyperry.errors import ConfigurationError 
  2   
3 -class ModelBridge(object):
4 """ 5 The C{ModelBridge} class is positioned between the processors and 6 middlewares in the L{adapter's request/response call stack 7 <AbstractAdapter>}. Before the response from an adapter call reaches the 8 C{ModelBridge}, the middlewares can only reliable work with the raw 9 response data. After the C{ModelBridge} handles the response, the 10 processors that follow can now operate on model instances (subclasses of 11 C{pyperry.Base}) instead of the raw response data. 12 13 On adapter reads, the C{ModelBridge} takes the list of records returned by 14 the adapter call and creates a model instance of the appropriate type for 15 each record in the list. 16 17 On adapter writes and deletes, the C{ModelBridge} class updates the state 18 of the model instance being saved or deleted to reflect 19 the data stored in the Response object returned by the adapter call. This 20 includes things like updating a model's C{saved} and C{new_record} 21 attributes in addition to putting error messages on the model if the 22 adapter received an error response. Additionally, the C{ModelBridge} will 23 refresh all of the model's data attributes (specified by calling 24 C{pyperry.Base.attributes(...)}) after a successful write if a read adapter 25 is configured for the model. 26 27 """ 28
29 - def __init__(self, next, options={}):
30 self.next = next 31 self.options = options
32
33 - def __call__(self, **kwargs):
34 results = self.next(**kwargs) 35 mode = kwargs['mode'] 36 37 if mode == 'read': 38 results = self.handle_read(results, **kwargs) 39 elif mode == 'write': 40 results = self.handle_write(results, **kwargs) 41 elif mode == 'delete': 42 results = self.handle_delete(results, **kwargs) 43 44 45 return results
46
47 - def handle_read(self, records, **kwargs):
48 """Create perry.Base instances from the raw records dictionaries.""" 49 if 'relation' in kwargs: 50 relation = kwargs['relation'] 51 records = [relation.klass(record, False) 52 for record in records if record] 53 return records
54
55 - def handle_write(self, response, **kwargs):
56 """Updates a model after a save.""" 57 if 'model' in kwargs: 58 model = kwargs['model'] 59 if response.success: 60 self.handle_write_success(response, model) 61 else: 62 self.handle_write_failure(response, model) 63 return response
64
65 - def handle_write_success(self, response, model):
66 """ 67 Updates the model's state attributes and retrieves a fresh version of 68 the data attributes if a read adapter is configured. 69 70 """ 71 has_read_adapter = True 72 try: 73 model.adapter('read') 74 except ConfigurationError: 75 has_read_adapter = False 76 77 if model.new_record and has_read_adapter: 78 setattr(model, model.pk_attr(), 79 response.model_attributes()[model.pk_attr()]) 80 81 if has_read_adapter: 82 model.reload() 83 84 model.saved = True 85 model.new_record = False
86
87 - def handle_write_failure(self, response, model):
88 """Updates the model instance when a save fails""" 89 model.saved = False 90 self.add_errors(response, model, 'record not saved')
91
92 - def handle_delete(self, response, **kwargs):
93 """Updates the model instance after a delete""" 94 if 'model' in kwargs: 95 model = kwargs['model'] 96 if response.success: 97 model.freeze() 98 else: 99 self.add_errors(response, model, 'record not deleted') 100 return response
101
102 - def add_errors(self, response, model, default_message):
103 """ 104 Copies the response errors to the model or uses a default error 105 message if the response errors are empty. 106 107 """ 108 errors = response.errors() 109 if len(errors) == 0: 110 errors = { 'base': default_message } 111 model.errors = errors
112