You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django:如何通过「参数包含字段部分值」过滤QuerySet?

如何用包含模型字段值的查询参数过滤Django的Place对象

首先提个小细节:你定义的Place模型里CharField必须指定max_length,否则Django会抛出错误,修正后的模型如下:

class Place(models.Model):
    name = models.CharField(max_length=255)  # 必填max_length参数

回到你的核心需求:你有一批带后缀的查询字符串(比如Starbucks Pike Place),需要找出所有Place对象,使得查询字符串包含该对象的name字段值(比如匹配到name="Starbucks"的记录)。下面给你几种实用的实现方式:

方法一:简单遍历法(适合数据量小的场景)

这种方法直观易懂,不需要复杂的ORM操作,直接遍历就能实现:

# 假设你的查询参数列表是这样的
query_strings = [
    "Starbucks Pike Place",
    "McDonald's Sand Lake Road",
    "Another Starbucks Out There"
]

matched_places = []
# 遍历所有Place对象
for place in Place.objects.all():
    # 转成小写实现不区分大小写匹配,不需要的话可以去掉.lower()
    place_name = place.name.lower()
    # 检查当前Place的name是否存在于任意一个查询字符串中
    for query in query_strings:
        if place_name in query.lower():
            matched_places.append(place)
            break  # 匹配到就跳出循环,避免重复添加

# 去重(因为可能多个查询字符串匹配同一个Place)
matched_places = list(set(matched_places))

方法二:用Q对象构建ORM查询(适合数据量中等的场景)

如果不想遍历所有对象,可以用Django的Q对象构建OR查询条件,直接在数据库层面过滤:

from django.db.models import Q

query_strings = [
    "Starbucks Pike Place",
    "McDonald's Sand Lake Road",
    "Another Starbucks Out There"
]

# 初始化空的查询条件
q_conditions = Q()
# 遍历每个查询字符串,收集匹配的name条件
for query in query_strings:
    # 先获取所有Place的name,检查是否在当前查询字符串里
    for place_name in Place.objects.values_list('name', flat=True):
        if place_name in query:
            q_conditions |= Q(name=place_name)

# 执行查询并去重
matched_places = Place.objects.filter(q_conditions).distinct()

方法三:利用数据库字符串函数(适合数据量大的场景)

如果你的数据库支持特定的字符串定位函数,可以直接在ORM中调用,查询效率会更高:

PostgreSQL(用STRPOS函数)

from django.db.models import Func, Value, Q

class StrPos(Func):
    function = 'STRPOS'
    output_field = models.IntegerField()

query_strings = [
    "Starbucks Pike Place",
    "McDonald's Sand Lake Road",
    "Another Starbucks Out There"
]

q_conditions = Q()
for query in query_strings:
    # STRPOS(query, name) > 0 表示name是query的子串
    q_conditions |= Q(name__isnull=False, strpos=StrPos(Value(query), 'name') > 0)

matched_places = Place.objects.filter(q_conditions).distinct()

MySQL(用LOCATE函数)

把上面的StrPos类改成:

class Locate(Func):
    function = 'LOCATE'
    output_field = models.IntegerField()

然后用Locate(Value(query), 'name') > 0即可。

SQLite(用INSTR函数)

改成:

class Instr(Func):
    function = 'INSTR'
    output_field = models.IntegerField()

使用Instr(Value(query), 'name') > 0。

注意事项

  • 如果需要忽略大小写的匹配,在方法一、二中可以统一转成小写;在方法三中,需要用数据库的大小写不敏感函数(比如PostgreSQL的strpos(lower(query), lower(name)))。
  • 如果你的Place表数据量很大,方法一的遍历效率会很低,优先选择方法二或三。

内容的提问来源于stack exchange,提问作者akwataip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:12:20