¿Cómo funcionan exactamente django serializers y vistas juntos? ¿Y cómo puedo devolver datos adicionales con mi consulta al frontend?

Estoy trabajando con un extremo frontal de react y un backend marco de descanso django, y estoy teniendo problemas para entender lo que sucede entre la vista y el serializador. Quiero devolver metadatos adicionales que no sean parte de la consulta al frente.

Aquí está el flujo de mi aplicación

Mi frontend llama un punto final:

Server.get("api/books-filtered")

Esto va a un camino en el backend escrito con marco de descanso django:

path("books-filtered/", Books.BookList.as_view()),

y luego

class Books(generics.RetrieveAPIView):
    serializer_class = BookSerializer
    lookup_field = 'id'
    lookup_url_kwarg = 'book_id'

    def get_queryset(self):
        """Return only queries pertaining to the patient"""
        return FilterOutSomeBookRelatedQuerySetHere()

cuya clase de serializador es:

class BookSerializer():
    class Meta:
        model = Book
        fields = ['Title','Author','Publisher']

Regreso al frente:

console.log(Server.get("api/books-filtered"))
// prints [
//{Title:"book 1", Author:"author 1", Publisher:"publisher 1"},
//{Title:"book 2", Author:"author 2", Publisher:"publisher 2"},
//{Title:"book 3", Author:"author 3", Publisher:"publisher 3"}
//] 

¿Qué pasa entre la vista y el serializador que hace que los datos sean formateados así para cuando se envía de vuelta al frontend?

¿Cómo puedo modificar lo que se imprime por consola.log (Server.get("api/books-filtered")) para incluir metadatos adicionales? Como

console.log(Server.get("api/books-filtered"))
// prints [
//{Title:"book 1", Author:"author 1", Publisher:"publisher 1"},
//{Title:"book 2", Author:"author 1", Publisher:"publisher 2"},
//{Title:"book 3", Author:"author 1", Publisher:"publisher 2"}, 
//[3 books, 2 separate publishers, 1 author]
//] 

o como:

console.log(Server.get("api/books-filtered"))
// prints 
// [{Title:"book 1", Author:"author 1", Publisher:"publisher 1", metadata:[1,2,3]},
//{Title:"book 2", Author:"author 1", Publisher:"publisher 2", metadata:[4,5,6]},
//{Title:"book 3", Author:"author 1", Publisher:"publisher 2", metadata:[7,8,9]}
//] 

Pregunta hecha hace 3 años, 4 meses, 26 días - Por algorithmwizard


3 Respuestas:

  • Explicar aquí cómo funciona DRF es un poco fuera de alcance pero responder a su pregunta sobre cómo agregar metadatos no es. Esto se puede hacer fácilmente mediante la ampliación de su clase de serializador como así:

    class BookSerializer(SurveySerializer):
        
        metadata = serializers.SerializerMethodField()
    
        def get_metadata(self, model_instance):
            # Use model instance or do another query all together
            return [1, 2, 3]
    
        class Meta:
            model = Book
            fields = ['title', 'author', 'publisher', 'metadata']
    

    Lo anterior dará lugar a:

    [
        {Title:"book 1", Author:"author 1", Publisher:"publisher 1", metadata:[1,2,3]},
        {Title:"book 2", Author:"author 1", Publisher:"publisher 2", metadata:[1,2,3]},
        {Title:"book 3", Author:"author 1", Publisher:"publisher 2", metadata:[1,2,3]}
    ]
    

    Usando SerializerMethodField puedes esencialmente poblar metadata campo con lo que quieras implementando get_metadata.

    Respondida el Dec 20, 2020 a las 16:46 - por pixelpioneerx

    Votos positivos: 0 | Votos negativos: 0

  • En Django, las vistas y los serializadores trabajan juntos para manejar las solicitudes de API y convertir los datos entre representaciones de Python y JSON (o cualquier otro formato). Aquí te explico brevemente cómo funciona el flujo en tu aplicación:

    • Cuando se realiza una solicitud desde el frontend al endpoint "api/books-filtered", Django envía esa solicitud a la vista asociada `Books.BookList.as_view()`.
    • La vista `BookList` se encarga de manejar la solicitud y procesarla. En tu caso, estás utilizando un `RetrieveAPIView`, lo que significa que estás recuperando solo un objeto en función de un parámetro de consulta (en este caso, "book_id"). Sin embargo, es posible que quieras utilizar una vista diferente dependiendo de tus necesidades, como una vista de lista (`ListAPIView`) si deseas devolver una lista de objetos.
    • La vista obtiene los datos requeridos de la base de datos utilizando el método `get_queryset()` para filtrar los objetos necesarios. En tu ejemplo, la vista devuelve un conjunto de consultas relacionadas con ciertos libros.
    • Una vez que la vista obtiene los datos, estos datos se pasan al serializador para convertirlos en JSON. El serializador `BookSerializer` define cómo se serializan los campos del modelo `Book` en formato JSON. En este caso, se han definido los campos 'Title', 'Author' y 'Publisher'.
    • Finalmente, el serializador procesa los datos y los envía de vuelta al frontend en formato JSON, como lo ves cuando imprimes `Server.get("api/books-filtered")`.

    Si deseas devolver metadatos adicionales junto con los datos de los libros, puedes personalizar tu serializador para incluir esos metadatos extra. Aquí te muestro cómo hacerlo:

    python
    class BookSerializer(serializers.ModelSerializer):
        metadata = serializers.ListField(child=serializers.IntegerField())
    
        class Meta:
            model = Book
            fields = ['Title', 'Author', 'Publisher', 'metadata']
    

    De esta manera, puedes incluir un campo 'metadata' en tu serializador que contendrá los metadatos adicionales que deseas enviar al frontend. Simplemente asegúrate de agregar los metadatos necesarios cuando estés preparando los datos en la vista antes de serializarlos.

    Luego, en tu vista, puedes modificar los datos antes de serializarlos para incluir los metadatos adicionales y así serán devueltos al frontend junto con los datos de los libros.

    Respondida el Dec 21, 2020 a las 16:47 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Cómo funcionan los serializers y vistas de Django juntos

    Los serializers de Django son responsables de convertir objetos de modelos en representaciones JSON que se pueden enviar a los clientes. Las vistas, por otro lado, manejan las solicitudes HTTP y devuelven las respuestas apropiadas.

    Cuando se llama a una vista genérica como RetrieveAPIView, primero ejecuta su método get_queryset para recuperar un conjunto de objetos de modelo. Luego, utiliza el serializador especificado en serializer_class para convertir estos objetos en JSON.

    Devolviendo datos adicionales con el frontend

    Opción 1: Incluir metadatos en el serializador

    Puedes modificar el serializador BookSerializer para incluir los metadatos adicionales que deseas devolver. Esto se puede hacer creando un campo adicional en la clase Meta:

    python
    class BookSerializer():
        class Meta:
            model = Book
            fields = ['Title', 'Author', 'Publisher', 'meta_data']  

    Agrega un campo meta_data

    Luego, en tu vista, puedes establecer el campo meta_data con los datos adicionales que deseas devolver. Por ejemplo:

    python
    class Books(generics.RetrieveAPIView):
        serializer_class = BookSerializer
        lookup_field = 'id'
        lookup_url_kwarg = 'book_id'
    
        def get_queryset(self):
            return FilterOutSomeBookRelatedQuerySetHere()
    
        def get_serializer_context(self):
            context = super().get_serializer_context()
            context['meta_data'] = [1, 2, 3]  

    Establece los metadatos aquí

    return context

    Opción 2: Mantener los datos adicionales separados

    Si no deseas incluir los metadatos en el serializador, puedes mantenerlos separados y devolverlos como un campo adicional en la respuesta de la vista. Por ejemplo:

    python
    class Books(generics.RetrieveAPIView):
        serializer_class = BookSerializer
        lookup_field = 'id'
        lookup_url_kwarg = 'book_id'
    
        def get_queryset(self):
            return FilterOutSomeBookRelatedQuerySetHere()
    
        def get_response_data(self, obj):
            data = super().get_response_data(obj)
            data['meta_data'] = [1, 2, 3]  

    Agrega los metadatos a la respuesta

    return data

    Respondida el Dec 21, 2020 a las 16:52 - por Gemini

    Votos positivos: 0 | Votos negativos: 0