Как сделать этот запрос на присоединение в Django - PullRequest
11 голосов
/ 14 мая 2009

В Django у меня есть две модели:

class Product(models.Model):
    name = models.CharField(max_length = 50)
    categories = models.ManyToManyField(Category)

class ProductRank(models.Model):
    product = models.ForeignKey(Product)
    rank = models.IntegerField(default = 0)

Я поместил ранг в отдельную таблицу, потому что при каждом просмотре страницы ранг будет меняться, и я волновался, что все эти записи приведут к замедлению моих других (в основном читаемых) запросов.

Я собираю список Products из простого запроса:

cat = Category.objects.get(pk = 1)
products = Product.objects.filter(categories = cat)

Теперь я хотел бы получить все звания для этих продуктов. Я бы предпочел сделать все это за один раз (используя соединение SQL), и мне было интересно, как это выразить с помощью механизма запросов Django.

Как правильно сделать это в Джанго?

Ответы [ 4 ]

14 голосов
/ 14 мая 2009

Это можно сделать в Django, но вам нужно будет немного изменить структуру своих моделей:

class Product(models.Model):
    name = models.CharField(max_length=50)
    product_rank = models.OneToOneField('ProductRank')

class ProductRank(models.Model):
    rank = models.IntegerField(default=0)

Теперь, когда вы выбираете объекты Product, вы можете отслеживать отношение один к одному в одном запросе, используя метод select_related () :

Product.objects.filter([...]).select_related()

В результате будет получен один запрос, который выбирает товарные ранги с помощью объединения:

SELECT "example_product"."id", "example_product"."name", "example_product"."product_rank_id", "example_productrank"."id", "example_productrank"."rank" FROM "example_product" INNER JOIN "example_productrank" ON ("example_product"."product_rank_id" = "example_productrank"."id")

Мне пришлось переместить поле отношения между Product и ProductRank в модель Product, поскольку похоже, что select_related () следует за внешними ключами только в одном направлении.

4 голосов
/ 14 мая 2009

Я не проверял, но:

products = Product.objects.filter(categories__pk=1).select_related()

Должен захватить каждый экземпляр.

2 голосов
/ 14 мая 2009

Добавьте вызов в метод QuerySet select_related (), хотя я не уверен, что ссылки в обоих направлениях получаются, это наиболее вероятный ответ.

1 голос
/ 03 октября 2018

для Django 2.1 Из документации

В этом примере извлекаются все объекты Entry с блогом, имя которого «Блог Битлз»:

 Entry.objects.filter(blog__name='Beatles Blog')

Док. URL https://docs.djangoproject.com/en/2.1/topics/db/queries/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...