Django中如何过滤genres数组包含指定ID的Film模型查询集?
如何过滤genres数组包含指定ID的电影
嘿,刚好我之前也处理过类似的需求,这得看你在Django里是用哪种字段来存储genres数组的,下面分两种常见情况来说:
情况1:使用PostgreSQL的ArrayField存储ID数组
如果你的Film模型里genres是用ArrayField(比如models.ArrayField(models.IntegerField()))定义的,那直接用__contains查询就能实现你要的效果——注意要把目标ID放到一个列表里传进去:
# 假设你要找包含genre_id=3的电影 target_genre_id = 3 result = Film.objects.filter(genres__contains=[target_genre_id])
这里要区分下__contains和__in的区别:
__in是判断字段值是否在给定的列表中(比如如果genres是单个ID的字段,那genres__in=[1,3]会找ID是1或3的电影)- 而针对
ArrayField的__contains,是判断数组字段是否包含列表中的任意元素(这里传单个元素的列表,就是找数组里有这个ID的电影)
如果你的Django版本是3.2及以上,也可以用__overlap,效果和单元素的__contains一致:
result = Film.objects.filter(genres__overlap=[target_genre_id])
情况2:用其他字段存储(比如逗号分隔的字符串,不推荐)
如果你的genres是用普通CharField存的逗号分隔ID(比如"1,4,7"),这种方式其实不太推荐(查询效率低且容易出bug),但如果不得不这么做,可以通过添加前后逗号的方式避免误匹配(比如把1和11区分开):
from django.db.models import Value, CharField from django.db.models.functions import Concat target_genre_id = 3 # 给genres字段前后加上逗号,变成",1,4,7,",然后查询是否包含",3," result = Film.objects.annotate( formatted_genres=Concat(Value(','), 'genres', Value(','), output_field=CharField()) ).filter(formatted_genres__contains=f',{target_genre_id},')
还是建议尽量换成ArrayField,不管是查询效率还是代码可读性都会好很多~
内容的提问来源于stack exchange,提问作者Vitali Skripka
相关产品推荐
相关产品推荐

