我已经创建了自定义查找。我将它用于查询,但是,当我这样做时,会抛出错误Related Field got invalid lookup: lcb
。
我假设这是因为此自定义查找未正确注册。正如您将在下面看到的那样,我已经尝试了几件事情,但我对这个问题感到很遗憾。
这是我的代码:
租户/ 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)
主要/ 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
我发现这很奇怪,因为the docs建议在AppConfig
或models.py
中注册查找。我尝试了这两件事,但都没有奏效。
回溯
Environment:
Request Method: GET
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 at /landlords/find-tenants/5/
Exception Value: Related Field got invalid lookup: lcb
到目前为止我尝试过的所有事情
MainConfig.ready()
功能find_tenants()
视图main/models.py
Field
而不是ManyToManyField
ManyToManyField.register_lookup()
而不是装饰器%s <@ %s
更改为%s = %s
。我认为问题可能是它认为我的SQL无效答案 0 :(得分:2)
看起来有些混乱可能会在django的后续版本中进行整理...下面的编辑1是1.10,但代码在提示中有所不同,所以现在可能已经修复了。您可以尝试升级到1.11并查看是否可以修复它。但是,如果不起作用,我在下面列出的选项仍值得一试。
我意识到我在最初的答案中误读了异常。实际上,被触发的异常是django.db.models.fields.related.ForeignObject.get_lookup
中的异常,并且那里的代码更清楚django不支持关系字段上的自定义查找:
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)
...
是一些事情是你可以尝试让它工作的一件事:
通过多对多关系在其中一个字段上实现自定义查找,因此您可以查询
applications = applications.filter(
pets__id__lcb=house.allowed_pets.values_list('id', flat=True))
我能够使用IN
运算符来实现这些方面的工作。
或者,您可以继承您正在使用的 编辑:我试过这个,但它并没有因为它比这更复杂,并且对于连接操作,它是右侧表中使用的ForeignObject
并覆盖get_lookup
,以便它不会为您的新运算符抛出异常。毫无疑问,为了让它工作起来,你必须做一些小提琴。Field
的隐式字段,因此将Field
子类化为左手表还不够。选项1绝对是正确的方法。
我认为异常告诉你django不会尝试对关系字段使用自定义查找。鉴于你提到它,我猜测pets
是ManyToManyField
,即关系字段,所以我猜你的查找已经注册,django只是拒绝使用它。< / p>
你正在点击(django.db.models.sql.query.Query.build_filter()
)的django中的代码是:
....
if field.is_relation:
# No support for transforms for relational fields
num_lookups = len(lookups)
if num_lookups > 1:
raise FieldError('Related Field got invalid lookup: {}'.format(lookups[0]))
....
我不能说我完全理解其基本原理,但这肯定会解释为什么你试图用来注册查询的机制得到相同的结果。
这似乎是一个记录不完整的问题。网上我唯一能找到的东西(搜索时间为10分钟)是this,其他人得出了同样的结论。