Django - 查询列表中的任何项目在多对多字段中的任何对象
Posted
技术标签:
【中文标题】Django - 查询列表中的任何项目在多对多字段中的任何对象【英文标题】:Django - Query for any objects where any item from list is in ManytoMany field 【发布时间】:2017-04-12 15:02:28 【问题描述】:我在 Django 中有一个模型,它有一个名为“accepted_insurance”的多对多字段。我有一个表单,它使用包含保险提供商列表的查询字符串提交获取请求。我正在尝试编写一个查询,上面写着“如果查询字符串列表中的任何项目都在多对多字段列表中,则过滤这些对象。”。是否有 Django 查询快捷方式?我尝试使用“包含”,但我收到了一个类型错误,即相关字段的查找无效,我确信这只会说明列表是否包含列表。
models.py
class Provider(models.Model):
title = models.CharField(max_length=255, null=True, blank=True)
first_name = models.CharField(max_length=255, null=True, blank=True)
middle_name = models.CharField(max_length=255, null=True, blank=True)
last_name = models.CharField(max_length=255, null=True, blank=True)
email = models.EmailField(null=True, blank=True)
phone = models.CharField(max_length=40, null=True, blank=True)
extension = models.CharField(max_length=10, null=True, blank=True)
company = models.CharField(max_length=255, null=True, blank=True)
age = models.IntegerField(null=True, blank=True)
about = models.TextField(default='', null=True, blank=True)
position = models.CharField(max_length=255, null=True, blank=True)
cost_per_session = models.CharField(max_length=255, null=True, blank=True)
accepts_insurance = models.BooleanField(default=False)
accepted_insurance = models.ManyToManyField('Insurance', blank=True)
payment_methods = models.ManyToManyField('PaymentMethod', blank=True)
request.GET
http://localhost:8004/directory/?search=timothy&insurance=cigna,aetna,optum_health,united_behavioral,blue_cross_blue_shield
<QueryDict: 'insurance': ['cigna,aetna,optum_health,united_behavioral,blue_cross_blue_shield'], 'search': ['timothy']>
views.py 查询
for param in request.GET:
if param.lower() == 'insurance':
all_providers = all_providers.filter(accepted_insurance__contains=param)
【问题讨论】:
【参考方案1】:__in
是您需要的运算符。
但是,您还有其他一些问题。首先不需要遍历查询字典;它是一个dict,你可以通过key访问它。
其次,您目前只有一个字符串;您需要使用split(',')
方法将其拆分为字符串列表。
第三,您需要根据 Insurance 模型上的字段进行实际过滤 - 大概它有一个“名称”字段。
所以:
insurance = request.GET.get('insurance', '').split(',')
all_providers = all_providers.filter(accepted_insurance__name__in=insurance)
【讨论】:
那么如果接受的保险有两个标题为“Blue Cross Blue Shield”和“Cigna”的对象,它会尝试查看这两个标题是否都在保险字典中吗? 没有。它将匹配在其接受的保险字段列表中具有任何名称的任何提供者。 太棒了,谢谢丹尼尔!一些查询快捷方式一开始听起来有点反直觉,但如果它有效,它就可以工作。 请注意,如果提供者匹配列表中的多个项目,它可能会在输出中出现两次;将.distinct()
添加到查询中以防止这种情况发生。
__in case insensitive 吗?以上是关于Django - 查询列表中的任何项目在多对多字段中的任何对象的主要内容,如果未能解决你的问题,请参考以下文章