Django queryset - 搜索名字和姓氏

13

我有一个 Django 应用程序,从用户的单个表中检索所有主题。我还实现了一个输入搜索表单, 这是执行的查询:

all_soggs =     Entity.objects.filter(lastname__istartswith=request.GET['query_term']).order_by('lastname')
if(all_soggs.count()==0):
    all_soggs = Entity.objects.filter(firstname__istartswith=request.GET['query_term']).order_by('firstname')

如您所见,查询首先按姓氏匹配项,然后按名字进行搜索。这种方法在我输入完整的姓名“firstaname lastname”或“lastname firstname”时无效,此时没有结果。如何修改查询以进行更好的搜索?

谢谢 - 卢克

4个回答

17

https://dev59.com/hmsz5IYBdhLWcg3wwKqh#17361729复制/粘贴:

from django.db.models import Q 

def find_user_by_name(query_name):
   qs = User.objects.all()
   for term in query_name.split():
     qs = qs.filter( Q(first_name__icontains = term) | Q(last_name__icontains = term))
   return qs

7

您需要Q对象,并且您还需要将查询拆分为单独的术语(因为没有名字与完整字符串“Firstname Lastname”匹配)。

这是一个通用搜索 - 调整查询以适应您的特定需求!

编辑:哎呀,我真的不喜欢使用reduce,因为它看起来很困惑,但是这些需要进行OR操作,我们无法进行更详细的版本,因为术语数量未知。

import operator
from django.db.models import Q

search_args = []
for term in request.GET['query_term'].split():
    for query in ('first_name__istartswith', 'last_name__istartswith'):
        search_args.append(Q(**{query: term}))

all_soggs = Entity.objects.filter(reduce(operator.or_, search_args))

为了说明如何使用Q对象,给定搜索条件“Firstname Lastname”,前一个查询等同于:
Entity.objects.filter(
    Q(first_name__istartswith="Firstname") | Q(last_name__istartswith="Firstname") |
    Q(first_name__istartswith="Lastname") | Q(last_name__istartswith="Lastname")
    )

2

虽然这是一个比较老的问题,但最近我也遇到了同样的问题,所以我想分享一个更加优雅的解决方案。

from django.db.models import Value as V
from django.db.models.functions import Concat

from ..models import User

def find_user_by_name(search_str) -> QuerySey[User]:
    q = User.objects.annotate(full_name=Concat('first_name', V(' '), 'last_name'))
    q = q.filter(full_name__icontains=search_str)
    return q

这是我找到的唯一解决方案,可以实现我想要的行为,即使用带有空格的全名字符串(“John Doe”)和部分字符串(“John Do”)进行搜索。


0

类似问题:Django中查询全名

query = request.GET.get('query')
entities = []

try:
    firstname = query.split(' ')[0]
    lastname  = query.split(' ')[1]
    entities += Entity.objects.filter(firstname__icontains=firstname,lastname__icontains=lastname)
    entities += Entity.objects.filter(firstname__icontains=lastname,lastname__icontains=firstname)

entities = set(entities)

回答问题两次并引用自己的答案有什么意义? - Omri Luzon
1
根据Stack Overflow的规则,即使您引用了链接,也必须给出完整的答案,因为链接可能会失效。 - atx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接