使用传递的参数作为Django查询字符串中的值

时间:2018-08-08 13:54:32

标签: python django

是否可以将传递的参数用作Django查询字符串中的值?

因此,让我们假设我想在term_listusernamedisplay_name等不同字段中搜索特定术语(在name中)。

而不是多次这样做:

q1_username = Q(username__icontains=term_list[0])
q1_email = Q(email__icontains=term_list[0])

q2_username = Q(display_name__icontains=term_list[0])
q2_email = Q(e_mail__icontains=term_list[0])

q3_username = Q(name__icontains=term_list[0])
q3_email = Q(emailaddress__icontains=term_list[0])

我希望能够以更通用的方式针对不同情况进行此操作:

q1_username = "display_name"
q1_email = "emailaddress"
q1 = build_query(term_list, q1_username, q1_email)

def build_query(term_list, passed_username, passed_email):
    q_username = Q(insert_passed_username_here__icontains=term_list[0])
    q_email = Q(insert_passed_email_here__icontains=term_list[0])
    # ...
    return query

如果我这样尝试,我会收到以下错误消息,这并不奇怪:Cannot resolve keyword 'insert_passed_username_here' into field.

如何使用passed_usernamepassed_email替换函数中的insert_passed_username_hereinsert_passed_email_here

编辑: 根据@ Tsang-Yi Shen的回答,我更新了功能,但仍然出现错误。因此,让我们这样编辑我的问题,以使情况更清楚:

我在这样的不同数据库中有几个用户名和电子邮件:

"""query 1"""
q1_username = Q(username__icontains=term_list[0])
q1_email = Q(email__icontains=term_list[0])

special_q1 = q1_username | q1_email
for term in term_list[1:]:
    special_q1.add((Q(username__icontains=term) | Q(email__icontains=term)), special_q1.connector)

"""query 2"""
q2_username = Q(name__icontains=term_list[0])
q2_email = Q(email__icontains=term_list[0])

special_q2 = crimenetwork_username | crimenetwork_email
for term in term_list[1:]:
    special_q2.add((Q(name__icontains=term) | Q(email__icontains=term)), special_q2.connector)

构建此代码后,然后按如下所示过滤结果:

context = {}
context["q1_user_list"] = Users1.objects.using("db1").filter(special_q1)
context["q2_user_list"] = Users2.objects.using("db2").filter(special_q2)

问题:我大约有30个这样的查询,并且希望能够以更通用的方式实现。

如何像打开字典那样实现此目的?

1 个答案:

答案 0 :(得分:3)

我经常先创建一个字典,然后解压缩它,例如:

def build_query(term_list, passed_username, passed_email):
    q_username_dict = {passed_username + '__icontains': term_list[0]}
    q_username = Q(**q_username_dict)
    q_email_dict = {passed_email + '__icontains': term_list[0]}
    q_email = Q(**q_email_dict)

尽管我仍在寻找更优雅的解决方案。

编辑:

由于您最终将所有Q放入了filter()中,因此我建议创建一个Q对象的列表:

def make_query(passed_username, passed_email, term_list):
     return [
         (Q(**{passed_username + '__icontains': term}) |
          Q(**{passed_email + '__icontains': term})
         for term in term_list
     ]

然后解压缩列表:

q_list = make_query('username', 'email', ['term01', 'term02'])
context["q1_user_list"] = Users1.objects.using("db1").filter(*q_list)

我也省去了.add().connector的使用,因为它应该等效于AND之间的Q操作。希望我不要误会你的意思