es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Necesito serializar un campo personalizado de notas AVG para mi API en Django.

models.py

from django.db import models
from django.db.models import Avg
from users.models import UserProfile
from subjects.models import Subject

class Note(models.Model):
    id<em>user = models.ForeignKey(UserProfile, on</em>delete=models.CASCADE, related<em>name='user</em>note')
    id<em>subject = models.ForeignKey(Subject, on</em>delete=models.CASCADE, related<em>name='subject</em>note')
    exam_note = models.IntegerField()

<pre><code>@property
def average_note(self):
    if hasattr(self, '_average_note'):
        return self._average_note
    return Note.objects.aggregate(Avg('exam_note'))
</code></pre>

Ese es mi modelo de Nota y necesito calcular el promedio de las notas para serializarlo y enviarlo en la respuesta de la solicitud

views.py

class AvgNoteViewSet(viewsets.ModelViewSet):
    serializer<em>class = AvgSerializer
    authentication</em>classes = (TokenAuthentication,)
    permission_classes = (NotePermissions,)

<pre><code>def get_queryset(self):
    return Note.objects.all().annotate(_average_note=Avg('exam_note'))
</code></pre>

Y este es mi método redefinido get_queryset para calcular las notas promedio, pero solo tengo una lista de notas como resultado de esa consulta, así: respuesta de la solicitud

serializers.py

class AvgSerializer(serializers.ModelSerializer):
    """
    Serializa el promedio de las notas
    """

<pre><code>average_note = serializers.SerializerMethodField()

def get_average_note(self, obj):
    return obj.average_note

class Meta:
    model = Note
    fields = ['average_note']
</code></pre>

Y este es mi serializador

Mi intención es intentar obtener un promedio de las notas de exámenes del usuario registrado, así que entiendo que debo intentar agrupar por el id del usuario y luego agregar el promedio. Esta es mi tabla PostgreSQL desde la que estoy haciendo la consulta: tabla de notas

Basé mi código en https://stackoverflow.com/questions/68953258/how-to-calculate-average-of-some-field-in-django-models-and-send-it-to-rest-api, pero estoy tratando de obtener un resultado similar a ejecutar la siguiente consulta:


SELECT avg(exam_note)
FROM public.notes_note x
group by id_user_id

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para obtener el promedio de exam_note agrupado por id_user_id, puedes actualizar el método get_queryset en views.py de la siguiente manera:

    from django.db.models import Avg
    
    class AvgNoteViewSet(viewsets.ModelViewSet):
        serializer_class = AvgSerializer
        authentication_classes = (TokenAuthentication,)
        permission_classes = (NotePermissions,)
    
        def get_queryset(self):
            # Obtener el usuario que ha iniciado sesión
            user = self.request.user
    
            # Filtrar las notas por el usuario que ha iniciado sesión
            notes = Note.objects.filter(id_user=user)
    
            # Agregar el promedio de las notas agrupadas por ID de usuario
            avg_notes = notes.values('id_user').annotate(average_note=Avg('exam_note'))
    
            return avg_notes
    

    Esto primero filtra las notas por el usuario que ha iniciado sesión y luego las agrupa según el campo id_user y calcula el promedio de todos los valores de exam_note para cada grupo. La consulta resultante contendrá los campos id_user y average_note.

    Luego puedes actualizar la clase AvgSerializer para incluir el campo id_user además del campo average_note:

    class AvgSerializer(serializers.ModelSerializer):
        """
        Serializa el promedio de notas
        """
    
        id_user = serializers.IntegerField()
        average_note = serializers.FloatField()
    
        class Meta:
            model = Note
            fields = ['id_user', 'average_note']
    

    Con estos cambios, la respuesta resultante contendrá los campos id_user y average_note para cada grupo.

Comments are closed.