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.

Traduce lo siguiente al español: Formatear un recuento entero en porcentaje dentro de la anotación en Django Rest. Para lograr esto en Django Rest, puedes utilizar la función `annotate` junto con la función `Cast` y `F` proporcionadas por Django: Supongamos que tienes un modelo llamado `ModeloEjemplo` con un campo de recuento llamado `recuento` y quieres formatear ese recuento en porcentaje dentro de una anotación. Aquí está cómo puedes hacerlo: 1. Importa las funciones necesarias al principio de tu archivo: “`python from django.db.models import F from django.db.models.functions import Cast “` 2. Luego, puedes usar estas funciones dentro de la anotación. Aquí hay un ejemplo de cómo puedes hacerlo: “`python from django.db.models import IntegerField, ExpressionWrapper ModeloEjemplo.objects.annotate( porcentaje_de_recuento=ExpressionWrapper( Cast((F(‘recuento’) / ModeloEjemplo.objects.aggregate(Sum(‘recuento’))[‘recuento__sum’]) * 100, output_field=IntegerField()), output_field=IntegerField(), ) ) “` En este ejemplo, `porcentaje_de_recuento` es el nombre del campo anotado que contendrá el valor del recuento formateado en porcentaje. 3. Puedes ajustar este código según tus necesidades, asegurándote de usar el nombre correcto del modelo y del campo de recuento en tu aplicación. Espero que esto te haya sido útil. Si tienes alguna otra pregunta, no dudes en preguntar.

Tengo que enviar el porcentaje de las cuentas en la llamada a la API en DRF. He calculado las cuentas y las he adjuntado a la consulta utilizando annotate. Pero en realidad necesito el porcentaje en lugar de la cuenta.

TYPES = ((1, 'frío'),
         (2, 'húmedo'),
         (3, 'caluroso'))

from django.db.models import Q,Count

class Destinations(models.Model):

   continent = models.CharField()
   /............/

class Packages(models.Model):

    location = models.Foreignkey(Destination,on_delete=models.CASCADE,related_name='packages')
    place_type = models.CharField(
                            max_length=1,
                            choices=TYPES,
                            default=''

Mi vista:

He utilizado la función de lista dentro de modelviewset, algo así:

Destiantion = Destination.objects.all().annotate(total_packages=Count('packages'),
 cold_count=Count('packages',filter=Q(packages__place_type=1)),                                                                   
 humid_count=Count('packages',filter=Q(packages__place_type=2)),
 hot_count =Count('packages',filter=Q(packages__place_type=3)))

Aquí obtengo la respuesta como las cuentas de los tipos de paquetes en los atributos, pero lo que quiero es el porcentaje de tipos de paquetes como el 25% haciendo cold_count*100/total_packages, pero no puedo usar esto dentro de annotate.

Hay un método count() que podría ser útil, pero si lo usara tendría que hacer 4 consultas separadas y podría escribir otra API solo para eso. Así que tengo que usar annotate. ¿Pero cómo?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para obtener el porcentaje de tipos de paquetes utilizando “annotate”, puedes utilizar la función ExpressionWrapper para realizar un cálculo basado en las cuentas. Aquí hay un ejemplo:

    from django.db.models import F, ExpressionWrapper, FloatField
    
    class DestinationViewSet(viewsets.ModelViewSet):
        queryset = Destination.objects.all()
        serializer_class = DestinationSerializer
    
        def get_queryset(self):
            queryset = super().get_queryset()
            queryset = queryset.annotate(
                total_packages=Count('packages'),
                cold_count=Count('packages', filter=Q(packages__place_type=1)),
                humid_count=Count('packages', filter=Q(packages__place_type=2)),
                hot_count=Count('packages', filter=Q(packages__place_type=3)),
                cold_percent=ExpressionWrapper(
                    F('cold_count') * 100 / F('total_packages'),
                    output_field=FloatField()
                ),
                humid_percent=ExpressionWrapper(
                    F('humid_count') * 100 / F('total_packages'),
                    output_field=FloatField()
                ),
                hot_percent=ExpressionWrapper(
                    F('hot_count') * 100 / F('total_packages'),
                    output_field=FloatField()
                )
            )
            return queryset
    

    En este ejemplo, estamos utilizando la función ExpressionWrapper para calcular el porcentaje basado en la cuenta y el total_packages. También estamos especificando el output_field como FloatField para obtener un valor decimal en lugar de un número entero.

    Ahora, cuando realizas una llamada a la API a este endpoint, la respuesta incluirá los valores de porcentaje para cada tipo de paquete junto con las cuentas:

    {
        "id": 1,
        "continent": "Europa",
        "total_packages": 100,
        "cold_count": 20,
        "humid_count": 40,
        "hot_count": 40,
        "cold_percent": 20.0,
        "humid_percent": 40.0,
        "hot_percent": 40.0
    }
    

Comments are closed.