OBTER produtos e imagens de dois modelos Django, filtrando o nome do produto e acessando o banco de dados apenas uma vez

Nov 29 2020

Tenho dois modelos Django para um site de comércio eletrônico:

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)

O usuário irá inserir algumas palavras-chave, e eu filtro os nomes dos produtos com essa palavra-chave e mostro apenas esses produtos. Com cada produto, na página de resultados, quero imediatamente que todas as miniaturas de seus produtos sejam carregadas e mostradas também.

Como posso recuperar os dois modelos no mesmo conjunto de visualizações e no mesmo queryset, de maneira eficiente?

Eu sei que posso conseguir isso com dois querysets separados, sendo um deles

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

e o outro conjunto de visualizações para as miniaturas

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

Posso não ter escrito o último da maneira mais correta, estou apenas escrevendo um pseudo-código, mas sei como fazer.

Meu ponto é, eu preciso fazer a mesma filtragem dos product_names com as palavras-chave de entrada duas vezes, uma para recuperar os nomes e descrições dos produtos, em um ProductViewset, e mais uma vez a mesma filtragem, para obter suas miniaturas, de um ThumbnailViewset.

Como faço para evitar isso e faço a filtragem apenas uma vez?

Eu sei como .select_related () funciona, que posso obter as tabelas de ambos os produtos de modelos e miniaturas com um único acerto no banco de dados. Mas como faço para mostrá-los juntos e retorná-los em um único queryset? Se eu retornar então em um único serializador, os campos nome e descrição do Produto serão repetidos, como:

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

Portanto, para cada miniatura, toda a product_description será repetida várias vezes e, como isso pode ter 10.000 caracteres, se muitos produtos forem exibidos na página, será lento para transferir esses dados do servidor para o cliente. Além disso, não preciso repetir a descrição para cada miniatura. Mas como obtenho a descrição do produto apenas uma vez, com todas as miniaturas do produto, da maneira mais eficiente?

Respostas

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

....