如何在不知道我将查询哪些字段的情况下构建Django查询?

时间:2016-06-22 22:28:36

标签: python mysql django

我是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())...

1 个答案:

答案 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(...)

代码是自我解释的。希望它有所帮助。