我是Django的新手,也是Python的新手,我正在尝试构建一个查询。我在字典中有一些字段,我不知道在查询中会使用哪些字段(它们来自表单。)
我有点工作,但我可以说它已经坏了,而且很糟糕,而不是可重复使用的代码:
if 'street_number' in params:
query = query.filter(addresses__street_number=params['street_number'])
if 'street_name' in params:
query = query.filter(addresses__street_name=params['street_name'])
if 'district' in params:
query = query.filter(addresses__district=params['district'])
if 'city' in params:
query = query.filter(addresses__city=params['city'])
if 'county' in params:
query = query.filter(addresses__county=params['county'])
if 'state' in params:
query = query.filter(addresses__state=params['state'])
if 'country' in params:
query = query.filter(addresses__country=params['country'])
if 'zip_code' in params:
query = query.filter(addresses__zip_code=params['zip_code'])
if 'precinct' in params:
query = query.filter(addresses__precinct=params['precinct'])
我相信每次调用query.filter时都会加入一次。当我查看它生成的SQL时,我看到了这个混乱:
SELECT `voters`.`id`, `voters`.`created_at`, `voters`.`updated_at`, `voters`.`first_name`, `voters`.`middle_name`, `voters`.`last_name`, `voters`.`name_prefix`, `voters`.`name_suffix`, `voters`.`ethnicity`, `voters`.`gender`, `voters`.`i360_id`, `voters`.`rnc_id`, `voters`.`congressional_voter_id`, `voters`.`state_voter_id`, `voters`.`county_voter_id`
FROM `voters`
INNER JOIN `voters_addresses` ON (`voters`.`id` = `voters_addresses`.`voter_id`)
INNER JOIN `addresses` ON (`voters_addresses`.`address_id` = `addresses`.`id`)
INNER JOIN `voters_addresses` T4 ON (`voters`.`id` = T4.`voter_id`)
INNER JOIN `addresses` T5 ON (T4.`address_id` = T5.`id`)
WHERE (`addresses`.`city` = Nashville AND T5.`state` = TN) LIMIT 10
(SQL中还有其他一些事情,比如加入手机,但这与此问题无关。)
请注意投票者地址和地址的额外加入。我可以重构这个,所以它使用一个filter()调用吗?或者,我可以从每个相关模型(地址,电话等)开始构建查询,并在以后以某种方式将它们组合起来吗?像
这样的东西Voter.objects
.whereExists(Address.objects.filter())
.whereExists(Phone.objects.filter())...
答案 0 :(得分:1)
没有内置的方法,你可以优化它。
def set_if_not_none(mapping, key, value):
if value is not None:
mapping[key] = value
def view(request):
sort_params = {}
get_params_needed = ['street_number', 'street_name', 'district'] # And list all of them you need.
for param in get_params_needed:
set_if_not_none(sort_params, 'addresses__' + param, request.GET.get(param))
result = YourObject.objects.filter(**sort_params)
...
return render(...)
代码是自我解释的。希望它有所帮助。