def resolve_field(model_field, lookup_expr): """ Resolves a ``lookup_expr`` into its final output field, given the initial ``model_field``. The lookup expression should only contain transforms and lookups, not intermediary model field parts. Note: This method is based on django.db.models.sql.query.Query.build_lookup For more info on the lookup API: https://docs.djangoproject.com/en/1.9/ref/models/lookups/ """ query = model_field.model._default_manager.all().query lhs = Expression(model_field) lookups = lookup_expr.split(LOOKUP_SEP) assert len(lookups) > 0 while lookups: name = lookups[0] # If there is just one part left, try first get_lookup() so # that if the lhs supports both transform and lookup for the # name, then lookup will be picked. if len(lookups) == 1: final_lookup = lhs.get_lookup(name) if not final_lookup: # We didn't find a lookup. We are going to interpret # the name as transform, and do an Exact lookup against # it. lhs = query.try_transform(lhs, name, lookups) final_lookup = lhs.get_lookup('exact') return lhs.output_field, final_lookup.lookup_name lhs = query.try_transform(lhs, name, lookups) lookups = lookups[1:]
def lookups_for_field(model_field): """ Generates a list of all possible lookup expressions for a model field. """ lookups = [] for expr, lookup in model_field.get_lookups().items(): if issubclass(lookup, Transform): transform = lookup(Expression(model_field)) lookups += [ LOOKUP_SEP.join([expr, sub_expr]) for sub_expr in lookups_for_transform(transform) ] else: lookups.append(expr) return lookups
def lookups_for_field(model_field): """ Generates a list of all possible lookup expressions for a model field. """ # This is a hack to work around: # https://github.com/django/django/pull/6906 if isinstance(model_field, ForeignObject): return ['exact', 'gt', 'gte', 'lt', 'lte', 'in', 'isnull'] lookups = [] for expr, lookup in six.iteritems(class_lookups(model_field)): if issubclass(lookup, Transform) and django.VERSION >= (1, 9): transform = lookup(Expression(model_field)) lookups += [ LOOKUP_SEP.join([expr, sub_expr]) for sub_expr in lookups_for_transform(transform) ] else: lookups.append(expr) return lookups