POBIERZ produkty i obrazy z dwóch modeli Django, filtrując nazwę produktu i uzyskując dostęp do bazy danych tylko raz

Nov 29 2020

Mam dwa modele Django dla witryny eCommerce:

class Product(models.Model):
    name=models.CharField(max_length=300)
    description=models.CharField(max_length=10000)

class Thumnbnail(models.Model):
    thumnbnail=models.ImageField(null=True)
    product=models.ForeignKey(Product, related_name='related_product', on_delete=models.CASCADE)

Użytkownik wprowadzi kilka słów kluczowych, a ja filtruję nazwy produktów za pomocą tego słowa kluczowego i wyświetlam tylko te produkty. Z każdym produktem chcę, aby na stronie wyników wyszukiwania natychmiast ładowano i wyświetlały się wszystkie jego miniatury.

Jak efektywnie pobrać oba modele z tego samego zestawu widoków i tego samego zestawu zapytań?

Wiem, że mogę to osiągnąć za pomocą dwóch oddzielnych zestawów zapytań, z których jeden jest

queryset = Product.objects.filter(name__contains="Fanta").all()
return queryset

i inny zestaw widoków dla miniatur

queryset = Product.objects.select_related('thumbnail').filter(name__contains="Fanta").all()
return queryset
# I will create another serializer to only show the thumbnails, for this specific queryset

Ostatniego mogłem nie napisać najbardziej poprawnie, po prostu piszę pseudokod, ale wiem, jak to zrobić.

Chodzi mi o to, że muszę dwukrotnie filtrować nazwy_produktów z wejściowymi słowami kluczowymi, raz, aby pobrać nazwy i opisy produktów, w zestawie ProductViewset, i jeszcze raz, aby uzyskać ich miniatury, z zestawu ThumbnailViewset.

Jak tego uniknąć i zrobić filtrowanie tylko raz?

Wiem, jak działa .select_related (), że mogę uzyskać obie tabele obu modeli produktów i miniatury za jednym trafieniem do bazy danych. Ale jak pokazać je razem i zwrócić w jednym zestawie zapytań? Jeśli wrócę wtedy do jednego serializatora, nazwa i opis pól z Product zostaną powtórzone, jako:

fields= [ product_id, product_name, product_description, thumbnail_id, thumbnail_filepath]

Tak więc dla każdej miniatury cały opis_produktu będzie się powtarzał wielokrotnie, a ponieważ może to być 10.000 znaków, jeśli na stronie jest wyświetlanych wiele produktów, przesyłanie tych danych z serwera do klienta będzie wolne. Poza tym nie potrzebuję powtarzania opisu dla każdej miniatury. Ale w jaki sposób mogę uzyskać opis produktu tylko raz, ze wszystkimi miniaturami produktów, w najbardziej efektywny sposób?

Odpowiedzi

1 AlexElizard Nov 30 2020 at 14:15

Если я правильно понял вопрос, попробуйте это

# serializers.py
from rest_framework import serializers
from .models import Product


class ProductSerializer(serializers.ModelSerializer):
     thumnbnails = serializers.PrimaryKeyRelatedField(many=True, read_only=True,sourse='related_product')

     class Meta:
        model = Product
        fields = ['name', 'description', 'thumnbnails']


# views.py
...
from .serializers import ProductSerializer

....

queryset = Product.objects.filter(name__contains="Fanta").prefetch_related('related_product')
serializer = ProductSerializer(queryset, many=True)
return serializer.data

....