Как отфильтровать набор запросов на основе связанных объектов, если он содержит данные в Django - PullRequest
0 голосов
/ 22 мая 2019

Я хочу отфильтровать и получить только те данные, которые связаны с данными связанных объектов, если данные связаны только с родительскими объектами. Например: У меня есть следующие модели:

class Collection(models.Model):
    date_of_collection=models.DateField()

class Product(models.Model):
    name=models.CharField(max_length=100)
    collection = models.ForeignKey(Collection)

class Price(models.Model):
    price = models.FloatField()
    products = models.ForeignKey(Products, on_delete=models.CASCADE)

и у меня есть данные, относящиеся к моделям как:

Collection:
+----+--------------------+
| id | date_of_collection |
+----+--------------------+
|  1 | 2019-01-17         |
|  2 | 2019-01-30         |
|  3 | 2019-02-01         |
|  4 | 2019-02-02         |
+----+--------------------+

Products:

 +----+--------------------------------+
 | id | name           | collection    |
 +----+--------------------------------+
 |  1 | product 1      | 3             |
 |  2 | product 2      | 1             |
 |  3 | product 3      | 1             |
 |  4 | product 4      | 4             |
 +----+--------------------------------+

Price:

| id     | price            | product               |
+--------+------------------+-----------------------+
| 1      | 10.00            | 1                     |
| 2      | 20.00            | 1                     |
| 3      | 12.00            | 3                     |
+--------+------------------+-----------------------+

здесь у меня есть цена, относящаяся только к продукту 1 и 3, поэтому я хочу только те продукты, основанные на наборе запросов, которые я хочу фильтровать только на основе определенной даты_коллекции.

Я пробовал следующий набор запросов:

collection_month = Collection.objects.filter(date_of_collection__month=2)
product = Product.objects.filter(collection_id__in=collection_month).exclude(price_set__price=None)

Это так, как я, или каким-то другим способом ... это иногда дает плохой результат. Как мне это сделать.

1 Ответ

1 голос
/ 22 мая 2019

Вы довольно близко.
Вы не должны сравнивать collection_id с реальными предметами коллекции - вы можете просто передать collection__in=collection_month.
Вы можете напрямую исключить продукты без price с price__isnull=True

В этом запросе будет использоваться подзапрос (WHERE):

collection_month = Collection.objects.filter(date_of_collection__month=2)
products = Product.objects.filter(collection__in=collection_month).exclude(price__isnull=True)

В этом запросе будет использоваться INNER JOIN, который, по слухам, будет быстрее :

products = Product.objects.filter(collection__date_of_collection__month=2).exclude(price__isnull=True)
...