问题描述
有模型
class Fabric(models.Model):
vendor_code = models.CharField(max_length=50)
color = models.CharField(max_length=50)
lot = models.CharField(max_length=50)
values = [
{'vendor_code': '123','color': 'aodfe','lot': 'some lot 1'},{'vendor_code': '456','color': 'adfae','lot': 'some lot 2'},{'vendor_code': '789','color': 'dvade','lot': 'some lot 3'},]
dict 对象中没有 id。如何让对象检查字段值列表(同时针对每个对象的所有 3 个值)? 我知道我可以在循环中一一查询:
for item in values:
fabric = Fabric.objects.filter(vendor_code=item['vendor_code'],color=item['color'],lot=item['lot'])
但是列表中的对象数量可能很大。如果对象存在,是否有任何正确的方法可以立即获取对象?或者至少让他们获得最少的数据库命中。
提前致谢!
解决方法
您可以像这样使用 in (__in
) 过滤器:
fabrics = Fabric.objects.filter(
vendor_code__in=[value['vendor_code'] for value in values],color__in=[value['color'] for value in values],lot__in=[value['lot'] for value in values],)
然而,这将迭代 values
列表 3 次,只迭代一次,使用以下内容:
vendor_codes = []
colors = []
lots = []
for value in values:
vendor_codes.append(value['vendor_code'])
colors.append(value['color'])
lots.append(value['lot'])
fabrics = Fabric.objects.filter(
vendor_code__in=vendor_codes,color__in=colors,lot__in=lots,)
要同时根据所有三个值进行过滤,您必须像这样使用 Q objects:
q_objects = []
for value in values:
q_objects.append(Q(
vendor_code=value['vendor_code'],color=value['color'],lot=value['lot']
)
)
final_q_object = Q()
for q_object in q_objects:
final_q_object.add(q_object,Q.OR)
fabrics = Fabric.objects.filter(final_q_object)
它的要点是获取这个查询:
Q(Q(a=i,b=j,c=k)) | Q(Q(a=l,b=m,c=n) | ...)
经过一些优化后的最终答案:
final_query = Q()
for item in values:
final_query.add(
Q(
vendor_code=value['vendor_code'],lot=value['lot']
),Q.OR
)
fabrics = Fabric.objects.filter(final_query)
,
您可以使用 field lookup "in"。
# get all the vendor codes in a list
vendor_code_list = []
for v in values:
vendor_code_list.append(v['vendor_code'])
# query all the fabrics
fabrics = Fabric.objects.filter(vendor_code__in=vendor_code_list)
,
如果您想匹配精确的值并且您确定您的项目键是有效的字段名称,您可以:
for item in values:
fabric = Fabric.objects.filter(**item)
否则,如果您想检查您的项目是否包含在现有项目中,您可以:
for item in values:
item_in = {'{}__in'.format(key):val for key,val in item.items()}
fabric = Fabric.objects.filter(**item_in)