python - Custom lookup is not being registered in Django -
i've created custom lookup. i'm using query, however, when so, error related field got invalid lookup: lcb
thrown.
i'm assuming because custom lookup isn't being registered properly. you'll see below, i've tried several things , i'm lost issue is.
here's code:
tenants/views.py
from main.lookups import * def find_tenants(request, house_id): house = houselisting.objects.get(pk=house_id) applications = housingapplication.objects.filter(date_from__gte=house.available_from) applications = applications.filter(pets__lcb=house.allowed_pets.values_list('id', flat=true)) context = {'house': house, 'applications': applications} return render(request, 'landlords/find-tenants.html', context)
main/lookups.py
from django.db.models import lookup, manytomanyfield # custom lookups @manytomanyfield.register_lookup class listcontainedby(lookup): lookup_name = 'lcb' def as_sql(self, compiler, connection): lhs, lhs_params = self.process_lhs(compiler, connection) rhs, rhs_params = self.process_rhs(compiler, connection) params = lhs_params + rhs_params return '%s <@ %s' % (lhs, rhs), params
i find strange, the docs suggest registering lookup in appconfig
, or in models.py
. i've tried both of these things , neither worked.
traceback
environment: request method: request url: http://127.0.0.1:8000/landlords/find-tenants/5/ django version: 1.10.2 python version: 2.7.12 installed applications: ['main.apps.mainconfig', 'tenants.apps.tenantsconfig', 'landlords.apps.landlordsconfig', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.humanize', 'django.contrib.postgres', 'imagekit'] installed middleware: ['django.middleware.security.securitymiddleware', 'django.contrib.sessions.middleware.sessionmiddleware', 'django.middleware.common.commonmiddleware', 'django.middleware.csrf.csrfviewmiddleware', 'django.contrib.auth.middleware.authenticationmiddleware', 'django.contrib.auth.middleware.sessionauthenticationmiddleware', 'django.contrib.messages.middleware.messagemiddleware', 'django.middleware.clickjacking.xframeoptionsmiddleware'] traceback: file "/users/mightyspaj/development/projects/housingfinder/lib/python2.7/site-packages/django/core/handlers/exception.py" in inner 39. response = get_response(request) file "/users/mightyspaj/development/projects/housingfinder/lib/python2.7/site-packages/django/core/handlers/base.py" in _legacy_get_response 249. response = self._get_response(request) file "/users/mightyspaj/development/projects/housingfinder/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response 187. response = self.process_exception_by_middleware(e, request) file "/users/mightyspaj/development/projects/housingfinder/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response 185. response = wrapped_callback(request, *callback_args, **callback_kwargs) file "/users/mightyspaj/development/projects/housingfinder/lib/python2.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view 23. return view_func(request, *args, **kwargs) file "/users/mightyspaj/development/projects/housingfinder/lib/python2.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view 23. return view_func(request, *args, **kwargs) file "/users/mightyspaj/development/projects/housingfinder/housingfinder/landlords/views.py" in find_tenants 132. applications = applications.filter(pets__lcb=house.allowed_pets.values_list('id', flat=true)) file "/users/mightyspaj/development/projects/housingfinder/lib/python2.7/site-packages/django/db/models/query.py" in filter 796. return self._filter_or_exclude(false, *args, **kwargs) file "/users/mightyspaj/development/projects/housingfinder/lib/python2.7/site-packages/django/db/models/query.py" in _filter_or_exclude 814. clone.query.add_q(q(*args, **kwargs)) file "/users/mightyspaj/development/projects/housingfinder/lib/python2.7/site-packages/django/db/models/sql/query.py" in add_q 1227. clause, _ = self._add_q(q_object, self.used_aliases) file "/users/mightyspaj/development/projects/housingfinder/lib/python2.7/site-packages/django/db/models/sql/query.py" in _add_q 1253. allow_joins=allow_joins, split_subq=split_subq, file "/users/mightyspaj/development/projects/housingfinder/lib/python2.7/site-packages/django/db/models/sql/query.py" in build_filter 1178. lookup_class = field.get_lookup(lookups[0]) file "/users/mightyspaj/development/projects/housingfinder/lib/python2.7/site-packages/django/db/models/fields/related.py" in get_lookup 694. raise typeerror('related field got invalid lookup: %s' % lookup_name) exception type: typeerror @ /landlords/find-tenants/5/ exception value: related field got invalid lookup: lcb
all things i've tried far
- registering lookup in
mainconfig.ready()
function - registering lookup in
find_tenants()
view - registering lookup in
main/models.py
- registering lookup
field
instead ofmanytomanyfield
- registering lookup using
manytomanyfield.register_lookup()
instead of decorator - changing
%s <@ %s
%s = %s
. thought issue might thinks sql invalid
edit 2
it looks of confusion might sorted out in later versions of django... edit 1 below 1.10, code different in tip perhaps has been fixed. try upgrading 1.11 , see if fixes it. options listed below still worth try if doesn't work.
edit 1
i realized misread exception in initial answer. actually, exception being hit 1 in django.db.models.fields.related.foreignobject.get_lookup
, , code there clearer django not support custom lookups on relational fields:
class foreignobject(relatedfield): ... def get_lookup(self, lookup_name): if lookup_name == 'in': return relatedin elif lookup_name == 'exact': return relatedexact elif lookup_name == 'gt': return relatedgreaterthan elif lookup_name == 'gte': return relatedgreaterthanorequal elif lookup_name == 'lt': return relatedlessthan elif lookup_name == 'lte': return relatedlessthanorequal elif lookup_name == 'isnull': return relatedisnull else: raise typeerror('related field got invalid lookup: %s' % lookup_name) ...
there are couple of things 1 thing try work though:
implement custom lookup on 1 of fields through many many relationship, you'd have query like
applications = applications.filter( pets__id__lcb=house.allowed_pets.values_list('id', flat=true))
i able along these lines work using
in
operator.alternatively, may able subclassedit: tried this, , didn't work because it's more complicated that, , join operation it's implicit field right-hand tableforeignobject
using , overrideget_lookup
doesn't throw exception new operator... no doubt there bit of fiddle you'd have work though.field
used, subclassingfield
left hand table not enough. option 1 seems right way go it.
original answer
i believe exception telling django won't attempt use custom lookups relational fields. given mention i'm guessing pets
manytomanyfield
, i.e. relational field, , guess lookup has been registered, django refusing use it.
the bit of code in django hitting (in django.db.models.sql.query.query.build_filter()
) is:
.... if field.is_relation: # no support transforms relational fields num_lookups = len(lookups) if num_lookups > 1: raise fielderror('related field got invalid lookup: {}'.format(lookups[0])) ....
i can't understand rationale, explain why whatever mechanism tried use register lookup got same result.
it seems not-very-well documented issue. thing online find out (with 10 minutes searching) this, else came same conclusion.
Comments
Post a Comment