Запрашивать элементы по атрибуту Foreignkey Relation, а также наиболее эффективно запрашивать иностранные атрибуты

Существует три модели

Product: Наличие идентификатора, имени

Storage: Имеет идентификатор, имя, цвет и ветку

ProductStorage: Сопоставляет каждый продукт со складом и имеет некоторые дополнительные атрибуты.

Я хочу перечислить все ProductStorages с определенным Storage.branch значением, сгруппированные по хранилищу, отображая также имя хранилища и цвет.

Возможно ли сделать это в одном запросе? Я новичок в Django и не знаю, как сделать это наиболее эффективным способом.

Я знаю, что могу запросить все ProductStorages и отфильтровать по веткам. Затем отсортировать их по хранилищам и запросить атрибуты хранилищ вторым запросом. Но я полагаю, что это не лучший способ сделать это.

Я бы инвертировал запрос: вместо запроса ProductStorage можно запросить Storage и использовать prefetch_related для получения связанных товаров, также я бы определил отношение между Storage и Product с помощью "through"

Тогда ваш запрос будет выглядеть примерно так:

Storage.objects.all().prefetch_related("products")

Или с .filter(branch=..)., если вы хотите отфильтровать ветку

Простой запрос со связанными Storage и ProductStorages:

from django.db.models import Prefetch

products = Product.objects.prefetch_related(
    Prefetch(
        'productstorage_set', ProductStorage.objects.select_related('storage')
    )
)

тогда мы можем сгруппировать элементы по соответствующим name и color:

from collections import defaultdict

for product in products:
    product.items = defaultdict(list)
    for item in product.productstorage_set.all():
        product.items[item.storage.name, item.storage.color].append(item)

и передайте products шаблону:

{% for product in products %}
    <h1>{{ product.name }}</h1>
    <ul>
    {% for key, val in product.items %}
        <li><b>{{ key.0 }} - {{ key.1 }}</b>
        {% for item in val %}
            <li>{{ item.name }} - {{ item.extra_attr }}</li>
        {% endfor %}
        </li>
    {% endfor %}
    </ul>
{% endfor %}
Вернуться на верх