Django按多对多关系按额外字段过滤

时间:2020-05-26 06:07:53

标签: python django

我有这种模型定义,我希望有一个产品列表,这些产品与各自产品的属性距离<40

class Product(models.Model):
    title = models.CharField(max_length=255)
    near_duplicate_images = models.ManyToManyField("self", through="NearDuplicate")

class NearDuplicate(models.Model):
    first_product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="first_product")
    second_product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="second_product")
    distance = models.IntegerField(null=True, blank=True)

我尝试这样做是为了直接访问该关系

p = Product.objects.filter(near_duplicate_images__distance__lt=40).prefetch_related('near_duplicate_images')

但是它引发了这个异常

django.core.exceptions.FieldError: Related Field got invalid lookup: distance

我也尝试过这样做

p = Product.objects.all().prefetch_related(Prefetch("near_duplicate_images", queryset=NearDuplicate.objects.filter(distance__lt=40), to_attr="near_duplicate_images_list"))

但是它引发了这个异常

django.core.exceptions.FieldError: Cannot resolve keyword 'near_duplicate_images_rel_+' into field. Choices are: distance, first_product, first_product_id, id, second_product, second_product_id

2 个答案:

答案 0 :(得分:0)

我认为您不需要“ near_duplicate_images”字段。 尝试类似的方法(尚未测试):

p = Product.objects.filter(title__in=NearDuplicate.object.filter(first_product=current_product, distance=40).values('second_product',)

QuerySet API - "_in"

答案 1 :(得分:0)

我认为这样的查询应该有效。您需要distance小于40的产品列表。

products = NearDuplicate.objects.filter(distance__lt=40).values('first_product', 'second_product')

这将提供类似于

的输出
<QuerySet [{'first_product': 1, 'second_product': 2}]>

更新-我在查询周围玩了一些。如果要获取first_productsecond_product中任何一个中存在的产品的绝对列表。您可能需要使用多个查询,例如

q1= NearDuplicate.objects.filter(distance__lt=40).values_list('first_product', flat=True)

这将输出为

<QuerySet [1]>

q2 = NearDuplicate.objects.filter(distance__lt=40).values_list('second_product', flat=True)

这将输出为

<QuerySet [2]>

第一个查询查询first_product中列出的所有产品,第二个查询列出second_product中存在的所有产品。现在,您可以将它们合并并使用以下查询取出不同的值

q1.union(q2).distinct()

这将使最终输出为

<QuerySet [1, 2]>

我希望它会有所帮助。 :)