def _get_field(model, name): # Create a fake query object so we can easily work out what field # type we are dealing with qs = Query(model) parts = name.split(LOOKUP_SEP) # The following is borrowed from the innards of Query.add_filter - it strips out __gt, __exact et al. num_parts = len(parts) if num_parts > 1 and parts[-1] in QUERY_TERMS: # Traverse the lookup query to distinguish related fields from # lookup types. for counter, field_name in enumerate(parts, 1): try: lookup_field = model._meta.get_field(field_name) except FieldDoesNotExist: # Not a field. Bail out. parts.pop() break # Unless we're at the end of the list of lookups, let's attempt # to continue traversing relations. if counter < num_parts: try: model = lookup_field.rel.to except AttributeError: # Not a related field. Bail out. parts.pop() break return qs.names_to_path(parts, qs.get_meta(), True, fail_on_missing=False)[1]
def _get_field(model, name): # Create a fake query object so we can easily work out what field # type we are dealing with parts = name.split(LOOKUP_SEP) # The following is borrowed from the innards of Query.add_filter - it strips out __gt, __exact et al. num_parts = len(parts) if num_parts > 1 and parts[-1] in Query.query_terms: # Traverse the lookup query to distinguish related fields from # lookup types. for counter, field_name in enumerate(parts, 1): try: lookup_field = model._meta.get_field(field_name) except FieldDoesNotExist: # Not a field. Bail out. parts.pop() break # Unless we're at the end of the list of lookups, let's attempt # to continue traversing relations. if counter < num_parts: try: model = lookup_field.rel.to except AttributeError: # Not a related field. Bail out. parts.pop() break qs = Query(model) return qs.names_to_path(parts, qs.get_meta(), True, fail_on_missing=False)[1]
def follow_model_field_lookup(model, lookup): """ Follow a model lookup `foreignkey__foreignkey__field` in the same way that Django QuerySet.filter() does, returning the final models.Field. """ query = Query(model) lookup_splitted = lookup.split(LOOKUP_SEP) _, field, _, _ = query.names_to_path(lookup_splitted, query.get_meta()) return field
def test_names_to_path_field(self): query = Query(None) query.add_annotation(Value(True), "value") path, final_field, targets, names = query.names_to_path(["value"], opts=None) self.assertEqual(path, []) self.assertIsInstance(final_field, BooleanField) self.assertEqual(len(targets), 1) self.assertIsInstance(targets[0], BooleanField) self.assertEqual(names, [])
def test_names_to_path_field_error(self): query = Query(None) msg = "Cannot resolve keyword 'nonexistent' into field." with self.assertRaisesMessage(FieldError, msg): query.names_to_path(["nonexistent"], opts=None)