簡體   English   中英

如何使用跨越關系和聚合函數的字段查找過濾 Django 模型?

[英]How can I filter Django models using field lookups that span relationships and aggregation functions?

我有一組代表出租物業的四個模型。

屬性model 存儲屬性的名稱和創建者。

class Property(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    creator = models.ForeignKey(User, related_name='creator', on_delete=models.PROTECT)
    name = models.CharField(max_length=100)

一個Property可以通過ForeignKey關系擁有多個Area實例。 Area也通過ForeignKey關系具有AreaType ,並且通過ManyToManyField具有許多便利設施

class Area(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    type = models.ForeignKey(AreaType, on_delete=models.PROTECT)
    property = models.ForeignKey(Property, on_delete=models.PROTECT)
    amenities = models.ManyToManyField(Amenity, null=True, blank=True)

class AreaType(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.CharField(max_length=100)


class Amenity(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.CharField(max_length=100)

我熟悉跨越關系和不跨越關系的字段查找,以及通過 kwargs 過濾。

我不熟悉的是結合字段查找和聚合函數。 因此,鑒於上述模型,我想:

  1. 檢索所有至少有 3 個設施名稱為“電視”的屬性。
  2. 檢索至少有 2 個 AreaType 名稱為“Bathroom”的屬性。

要檢索具有名稱為電視的設施的所有屬性:

非常感謝@Waldemar Podsiadło,我誤解了這個問題。 他提供了計算電視的正確答案。
Property.objects.filter(area_set__amenities__name="Television")\
    .annotate(tv_count=models.Count('area_set__amenities')\
    .filter(tv_count__gte=3))

應檢索與名稱為電視的便利設施相關的所有屬性。

區域也可以這樣做,但讓我們走捷徑:

Property.objects.filter(
    area_set__type__name="Bathroom",
    area_set__type__count__gte=2
)

您沒有定義related_name ,因此 area 的反面將是area_set 從那里開始,您可以將屬性作為字段提供給您,因此您可以繼續從中過濾。

要訪問查詢中的字段,請使用雙下划線__將其分隔,這也適用於__count__sum等表達式。

指向django-docs的鏈接,以了解有關查詢集和過濾的更多信息。

指向django-docs的鏈接以了解有關過濾的更多信息。

@nigel239 我認為您不需要在過濾反向關系中使用 _set,您只需使用 model 名稱即可。 此外,您可以使用 Django ORM 制作更多內容。 對於第一個問題,它是這樣的:

Property.objects.filter(area__amenities__name="Television")
        .annotate(tv_ocurance=Count('area__amenities', filter=Q(area__amenities__name="Television")))
        .filter(tv_ocurance__gte=3)

您可以對第二個查詢執行完全相同的操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM