@@ -47,6 +47,14 @@ def _inject_params(self):
4747 if not any ((self .app_name , self .model_name )):
4848 raise InvalidRequest ('app_name or model_name missing' )
4949
50+ @property
51+ def fk_refs_in_fields (self ):
52+ refs = []
53+ for field in self .fields :
54+ if '__' in field :
55+ refs .append (field .rsplit ('__' , 1 )[0 ])
56+ return refs
57+
5058
5159class ModelConfig (object ):
5260 def __init__ (self , app_name , model_name ):
@@ -175,23 +183,10 @@ def _apply_opts(self):
175183 elif qset_opt == 'limit' :
176184 self .qset = self .qset [:self .params .limit ]
177185 elif isinstance (value , list ):
178- # handle values case separately
179- if qset_opt == 'values' :
180- # list of parameters passed in values function
181- values_params = set (value ) - \
182- self .model_config .get_properties ()
183- # list of properties handled separately
184- properties = set (value ) - values_params
185- try :
186- # qset.values(*fields) is called but not yet evaluated
187- qset_values = func (* values_params )
188- except FieldError as e :
189- raise InvalidModelFieldName (str (e ))
190- if self .query_has_properties ():
191- # queryset evaluated
192- qset_values = self ._add_properties (
193- qset_values , properties )
194- self .qset = qset_values
186+ # handle values case where property is passed in fields
187+ if qset_opt == 'values' and self .query_has_properties ():
188+ # returns DBRows instance
189+ self .qset = self ._add_fields ()
195190 else :
196191 try :
197192 self .qset = func (* value )
@@ -207,24 +202,25 @@ def query_has_properties(self):
207202 return bool (set (self .params .fields ).intersection (
208203 self .model_config .get_properties ()))
209204
210- def _add_properties (self , db_rows , query_properties ):
211- # evaluate queryset values
212- db_rows = list (db_rows )
205+ def _add_fields (self ):
213206 qset_values = DBRows ()
214- # skipping select_related call, expecting
215- # properties will not have references call
216- # like machine.os.arch in any of the machine's property
217- logger .debug ('Request parameters: %s \n Query (2nd call): %s\n ' ,
207+ self .qset = self .qset .select_related (* self .params .fk_refs_in_fields )
208+ logger .debug ('Request parameters: %s \n Query: %s\n ' ,
218209 self .params .params , self .qset .query )
219- for i , row in enumerate (self .qset ):
220- for field in query_properties :
221- try :
222- model_property = getattr (row , field )
223- except AttributeError :
224- raise InvalidModelFieldName (
225- 'Query field "%s" does not exists.' % field )
226- db_rows [i ][field ] = model_property
227- qset_values .append (db_rows [i ])
210+ for row in self .qset :
211+ model_fields = {}
212+ for field in self .params .fields :
213+ attr = row
214+ for ref in field .split ('__' ):
215+ try :
216+ attr = getattr (attr , ref )
217+ if attr is None :
218+ break
219+ except AttributeError :
220+ raise InvalidModelFieldName (
221+ 'Invalid query for field %s in %s.' % (ref , attr ))
222+ model_fields [field ] = attr
223+ qset_values .append (model_fields )
228224 return qset_values
229225
230226 def queryset (self ):
0 commit comments