30 from soc.logic import out_of_band |
30 from soc.logic import out_of_band |
31 |
31 |
32 |
32 |
33 def getFullClassName(cls): |
33 def getFullClassName(cls): |
34 """Returns fully-qualified module.class name string.""" |
34 """Returns fully-qualified module.class name string.""" |
|
35 |
35 return '%s.%s' % (cls.__module__, cls.__name__) |
36 return '%s.%s' % (cls.__module__, cls.__name__) |
36 |
37 |
37 |
38 |
38 def buildTypedQueryString(base_class, derived_class=None): |
39 def buildTypedQueryString(base_class, derived_class=None): |
39 """Returns a GQL query string compatible with PolyModel. |
40 """Returns a GQL query string compatible with PolyModel. |
44 derived_class: optional more-specific Model class that |
45 derived_class: optional more-specific Model class that |
45 derives from base_class, such as soc.models.document.Document; |
46 derives from base_class, such as soc.models.document.Document; |
46 default is None, in which case the inheritance_line |
47 default is None, in which case the inheritance_line |
47 property is *not* tested by the returned query string |
48 property is *not* tested by the returned query string |
48 """ |
49 """ |
|
50 |
49 query_str_parts = ['SELECT * FROM ', base_class.__name__] |
51 query_str_parts = ['SELECT * FROM ', base_class.__name__] |
50 |
52 |
51 if derived_class: |
53 if derived_class: |
52 query_str_parts.extend( |
54 query_str_parts.extend( |
53 [" WHERE inheritance_line = '", getFullClassName(derived_class), "'"]) |
55 [" WHERE inheritance_line = '", getFullClassName(derived_class), "'"]) |
62 base_class, derived_class: see buildTypedQueryString() |
64 base_class, derived_class: see buildTypedQueryString() |
63 order_by: optional field name by which to order the query results; |
65 order_by: optional field name by which to order the query results; |
64 default is None, in which case no ORDER BY clause is placed in |
66 default is None, in which case no ORDER BY clause is placed in |
65 the query string |
67 the query string |
66 """ |
68 """ |
|
69 |
67 query_str_parts = [ |
70 query_str_parts = [ |
68 buildTypedQueryString(base_class, derived_class=derived_class)] |
71 buildTypedQueryString(base_class, derived_class=derived_class)] |
69 |
72 |
70 if order_by: |
73 if order_by: |
71 query_str_parts.extend([' ORDER BY ', order_by]) |
74 query_str_parts.extend([' ORDER BY ', order_by]) |
80 Args: |
83 Args: |
81 limit: max amount of entities to return |
84 limit: max amount of entities to return |
82 offset: optional offset in entities list which defines first entity to |
85 offset: optional offset in entities list which defines first entity to |
83 return; default is zero (first entity) |
86 return; default is zero (first entity) |
84 """ |
87 """ |
|
88 |
85 query_string = buildOrderedQueryString( |
89 query_string = buildOrderedQueryString( |
86 base_class, derived_class=derived_class, order_by=order_by) |
90 base_class, derived_class=derived_class, order_by=order_by) |
87 |
91 |
88 query = db.GqlQuery(query_string) |
92 query = db.GqlQuery(query_string) |
89 |
93 |
107 of the supplied (non-None) fields |
111 of the supplied (non-None) fields |
108 OR |
112 OR |
109 possibly None if query had no results for the supplied field |
113 possibly None if query had no results for the supplied field |
110 that was used. |
114 that was used. |
111 """ |
115 """ |
|
116 |
112 # SELECT * FROM base_class WHERE inheritance_line = 'derived_class' |
117 # SELECT * FROM base_class WHERE inheritance_line = 'derived_class' |
113 typed_query_str = buildTypedQueryString( |
118 typed_query_str = buildTypedQueryString( |
114 base_class, derived_class=derived_class) |
119 base_class, derived_class=derived_class) |
115 |
120 |
116 if derived_class: |
121 if derived_class: |
144 if that offset would be less than zero |
149 if that offset would be less than zero |
145 OR |
150 OR |
146 None if there are no nearest entities or the offset of the beginning of |
151 None if there are no nearest entities or the offset of the beginning of |
147 the range cannot be found for some reason |
152 the range cannot be found for some reason |
148 """ |
153 """ |
|
154 |
149 # find entity "nearest" to supplied fields |
155 # find entity "nearest" to supplied fields |
150 nearest_entities, field = getNearestEntities( |
156 nearest_entities, field = getNearestEntities( |
151 base_class, fields_to_try, derived_class=derived_class) |
157 base_class, fields_to_try, derived_class=derived_class) |
152 |
158 |
153 if not nearest_entities: |
159 if not nearest_entities: |
201 """"Returns User entity for key_name or None if not found. |
207 """"Returns User entity for key_name or None if not found. |
202 - |
208 - |
203 - Args: |
209 - Args: |
204 - key_name: key name of entity |
210 - key_name: key name of entity |
205 """ |
211 """ |
|
212 |
206 return self._model.get_by_key_name(key_name) |
213 return self._model.get_by_key_name(key_name) |
207 |
214 |
208 def getFromFields(self, **kwargs): |
215 def getFromFields(self, **kwargs): |
209 """Returns the entity for a given link name, or None if not found. |
216 """Returns the entity for a given link name, or None if not found. |
210 |
217 |
211 Args: |
218 Args: |
212 link_name: a link name of the entity that uniquely identifies it |
219 **kwargs: the fields of the entity that uniquely identifies it |
213 """ |
220 """ |
214 # lookup by Sponsor key name |
221 |
215 key_name = self.getKeyNameForFields(**kwargs) |
222 key_name = self.getKeyNameForFields(**kwargs) |
216 |
223 |
217 if key_name: |
224 if key_name: |
218 entity = self._model.get_by_key_name(key_name) |
225 entity = self._model.get_by_key_name(key_name) |
219 else: |
226 else: |
220 entity = None |
227 entity = None |
221 |
228 |
222 return entity |
229 return entity |
223 |
230 |
224 def getIfFields(self, **kwargs): |
231 def getIfFields(self, **kwargs): |
225 """Returns Sponsor entity for supplied link name if one exists. |
232 """Returns entity for supplied link name if one exists. |
226 |
233 |
227 Args: |
234 Args: |
228 link_name: a link name of the Sponsor that uniquely identifies it |
235 **kwargs: the fields of the entity that uniquely identifies it |
229 |
236 |
230 Returns: |
237 Returns: |
231 * None if link name is false. |
238 * None if a field is false. |
232 * Sponsor entity for supplied link_name |
239 * Eentity for supplied fields |
233 |
240 |
234 Raises: |
241 Raises: |
235 out_of_band.ErrorResponse if link name is not false, but no Sponsor entity |
242 out_of_band.ErrorResponse if link name is not false, but no Sponsor entity |
236 with the supplied link name exists in the Datastore |
243 with the supplied link name exists in the Datastore |
237 """ |
244 """ |
|
245 |
238 if not all(kwargs.values()): |
246 if not all(kwargs.values()): |
239 # exit without error, to let view know that link_name was not supplied |
247 # exit without error, to let view know that link_name was not supplied |
240 return None |
248 return None |
241 |
249 |
242 entity = self.getFromFields(**kwargs) |
250 entity = self.getFromFields(**kwargs) |
246 return entity |
254 return entity |
247 |
255 |
248 fields = [] |
256 fields = [] |
249 |
257 |
250 for key, value in kwargs.iteritems(): |
258 for key, value in kwargs.iteritems(): |
251 fields.extend('"%s" is "%s"' % (key, value)) |
259 fields.extend('"%s" is "%s" ' % (key, value)) |
252 |
260 |
253 # else: fields were supplied, but there is no Entity that has it |
261 # else: fields were supplied, but there is no Entity that has it |
254 raise out_of_band.ErrorResponse( |
262 raise out_of_band.ErrorResponse( |
255 'There is no %s with %s.' % (self._name, ''.join(fields)), status=404) |
263 'There is no %s with %s.' % (self._name, ''.join(fields)), status=404) |
256 |
264 |
257 def getKeyNameForFields(self, **kwargs): |
265 def getKeyNameForFields(self, **kwargs): |
258 """Return a Datastore key_name for a Sponsor from the link name. |
266 """Return a Datastore key_name for a Entity from the specified fields. |
259 |
267 |
260 Args: |
268 Args: |
261 link_name: a link name of the entity that uniquely identifies it |
269 **kwargs: the fields of the entity that uniquely identifies it |
262 """ |
270 """ |
|
271 |
263 if not all(kwargs.values()): |
272 if not all(kwargs.values()): |
264 return None |
273 return None |
265 |
274 |
266 return self._keyName(**kwargs) |
275 return self._keyName(**kwargs) |
267 |
276 |
271 Args: |
280 Args: |
272 limit: max amount of entities to return |
281 limit: max amount of entities to return |
273 offset: optional offset in entities list which defines first entity to |
282 offset: optional offset in entities list which defines first entity to |
274 return; default is zero (first entity) |
283 return; default is zero (first entity) |
275 """ |
284 """ |
|
285 |
276 query = self._model.all() |
286 query = self._model.all() |
277 return query.fetch(limit, offset) |
287 return query.fetch(limit, offset) |
278 |
288 |
279 def updateModelProperties(self, model, **model_properties): |
289 def updateModelProperties(self, model, **model_properties): |
280 """Update existing model entity using supplied model properties. |
290 """Update existing model entity using supplied model properties. |
285 properties and their values |
295 properties and their values |
286 |
296 |
287 Returns: |
297 Returns: |
288 the original model entity with any supplied properties changed |
298 the original model entity with any supplied properties changed |
289 """ |
299 """ |
|
300 |
290 def update(): |
301 def update(): |
291 return self._unsafeUpdateModelProperties(model, **model_properties) |
302 return self._unsafeUpdateModelProperties(model, **model_properties) |
292 |
303 |
293 return db.run_in_transaction(update) |
304 return db.run_in_transaction(update) |
294 |
305 |
295 def _unsafeUpdateModelProperties(self, model, **model_properties): |
306 def _unsafeUpdateModelProperties(self, model, **model_properties): |
296 """(see updateModelProperties) |
307 """(see updateModelProperties) |
297 |
308 |
298 Like updateModelProperties(), but not run within a transaction. |
309 Like updateModelProperties(), but not run within a transaction. |
299 """ |
310 """ |
|
311 |
300 properties = model.properties() |
312 properties = model.properties() |
301 |
313 |
302 for prop in properties.values(): |
314 for prop in properties.values(): |
303 name = prop.name |
315 name = prop.name |
304 |
316 |
313 |
325 |
314 def updateOrCreateFromKeyName(self, properties, key_name): |
326 def updateOrCreateFromKeyName(self, properties, key_name): |
315 """Update existing entity, or create new one with supplied properties. |
327 """Update existing entity, or create new one with supplied properties. |
316 |
328 |
317 Args: |
329 Args: |
318 link_name: a link_name of the entity that uniquely identifies it |
330 properties: dictionairy with entity properties and their values |
319 **properties: keyword arguments that correspond to entity |
331 key_name: the key_name of the entity that uniquely identifies it |
320 properties and their values |
|
321 |
332 |
322 Returns: |
333 Returns: |
323 the entity corresponding to the key_name, with any supplied |
334 the entity corresponding to the key_name, with any supplied |
324 properties changed, or a new entity now associated with the |
335 properties changed, or a new entity now associated with the |
325 supplied key_name and properties. |
336 supplied key_name and properties. |