最小化Django中的DB命中:.values_list()依赖于先前的.filter()子句

时间:2012-04-05 07:38:33

标签: python django

我在Django中遇到数据库查询问题。

我的数据库(models.py):

class Food(models.Model):
    name = models.CharField(max_length=200)
    ...

class Combination(models.Model):
    food1 = models.ForeignKey(Food, related_name='food1')
    food2 = models.ForeignKey(Food, related_name='food2')
    ...

组合食物的顺序对我的问题无关紧要。
此外,每个组合可以存在多次(并且在两个方向上)。

E.g。 food1 =“巧克力”& food2 =“fruit”与food2 =“chocolate”&食物1 =“果”
两种组合都存在多次。

如果我想找到包括特定食物在内的所有组合(由food_id确定)
我目前正在使用以下查询:

combinations1 = Combination.objects.filter(food1=food_id).values_list('food2')
combinations2 = Combination.objects.filter(food2=food_id).values_list('food1')

它可以工作,但稍后需要更多处理。我尝试使用带有OR的Q对象, 但我没有成功,因为提取的列取决于过滤器......

我知道这个解决方案远非优雅。我是否应该使用自定义字段或CommaSeparatedIntegerField而不是两个单独的食物字段? 有没有办法通过一个DB命中获取所有请求的值(来自两列)?

感谢帮助我!

干杯,
奥利弗

2 个答案:

答案 0 :(得分:2)

我认为你最好的选择是使用Q对象,比如

qs = Combination.objects.filter(Q(food1=food_id)|Q(food2=food_id).values_list('food1', 'food2')
combinations = set()
for row in qs:
   if row[0] == food_id:
       combinations.append(row[1])
   else:
       combinations.append(row[0])

答案 1 :(得分:2)

itertools.chain(Food(id=food_id).food1.all(), Food(id=food_id).food2.all())

你在追求什么?

如果食物组合的顺序无关紧要,为什么不在ManyToManyField(Food)使用Combination? 然后Food(id=food_id).combination_set.all()将是其中包含特定食物的所有组合。