首页 > 解决方案 > 在 django 的查询字符串中使用传递的参数作为值

问题描述

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

所以,假设我想term_list在不同的字段中搜索特定的术语 (in ),username例如display_namename

而不是多次这样做:

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_usernameandpassed_email替换函数中的insert_passed_username_hereand insert_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 个这样的查询,并且希望能够以更通用的方式进行。

我怎样才能通过像字典解包来实现这一点?

标签: pythondjango

解决方案


我经常先创建一个字典,然后将其解包,例如:

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)

虽然我仍在寻找更优雅的解决方案。

编辑:

由于您最终将所有Qs 放入 afilter()中,因此我建议创建一个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)

我也消除了 and 的使用,.add()因为.connector它应该等同于sAND之间的操作Q。希望我没有误解你的意思


推荐阅读