Cómo hacer un QuerySet en Django devolviendo la última fecha

Estoy tratando de hacer un QuerySet usando Django, quiero devolver la última fecha de la base de datos, con los otros campos, usé prefetch_related(). El Max('data') usó todos los registros en la base de datos, no sólo los recientes.

Estos son mis modelos:

#models.py
    class TServices(models.Model):
            services = models.ForeignKey(Services, on_delete=models.CASCADE)
            servName = models.CharField(max_length=50)
        
            def __str__(self):
                return self.nomeServ
            
        class Control(models.Model):
            customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
            date = models.DateTimeField(null=True, blank=True)
        
            def __str__(self):
                return '%s' % self.date
        
            class Meta:
                get_latest_by = "date"
        
        class ServiceStatus(models.Model):
            control = models.ForeignKey(Control, on_delete=models.CASCADE)
            services_type = models.ForeignKey(TServices, on_delete=models.CASCADE)
            status = models.CharField(max_length=10)
        
            def __str__(self):
                return '%s' % self.status

Mis puntos de vista, donde hago la consulta en Django:

#views.py
def integr(request, servico):
    customer = Customer.objects.all().order_by('name')
    services = Services.objects.filter(servName__iexact=services)
    control = Control.objects.prefetch_related('servicestatus_set').annotate(Max('date'))
    context= {
        'customers': customer,
        'controls': control,
    }
    return render(request, 'app/integr.html', context)

Esta es la consulta que hice en mi base de datos y devolví la fecha reciente con la customer_id.

select max(date), app_control.customer_id from app_control
inner join app_servicestatus on
    app_servicestatus.control_id = app_control.id
inner join app_tservices on 
     app_tservices.id = app_servicestatus.services_type_id
where
    app_tservices.services_id = 1
group by app_control.customer_id

Pregunta hecha hace 3 años, 4 meses, 29 días - Por scriptsculptorbf10


2 Respuestas:

  • Para obtener la fecha más reciente para cada cliente en tu vista de Django, puedes utilizar la función Subquery y OuterRef en combinación con Max y Filter. Aquí te dejo el código actualizado para tu vista integr:

    python
    from django.db.models import Subquery, OuterRef, Max, F
    
    def integr(request, servicio):
        customers = Customer.objects.all().order_by('name')
        services = Services.objects.get(servName__iexact=servicio)
    
        subquery = Control.objects.filter(customer_id=OuterRef('customer_id')).values('customer_id').annotate(latest_date=Max('date'))
    
        control = Control.objects.filter(customer_id=OuterRef('customer_id'), date=Subquery(subquery.values('latest_date'))).filter(servicestatus__services_type__services=services)
    
        context = {
            'customers': customers,
            'controls': control,
        }
        return render(request, 'app/integr.html', context)
    

    En este código, se crea una subconsulta (subquery) que obtiene la fecha más reciente (latest_date) para cada cliente. Luego, se filtra la consulta principal para que solo devuelva los objetos Control cuya fecha coincida con la fecha más reciente obtenida en la subconsulta y que estén asociados al servicio services especificado.

    Espero que esto te ayude a obtener la fecha más reciente para cada cliente en tu vista de Django. ¡Déjame saber si necesitas más ayuda!

    Respondida el Dec 18, 2020 a las 14:39 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El problema que estás encontrando probablemente se deba a tu consulta en Control.objects.prefetch_related('servicestatus_set').annotate(Max('date')). La función annotate() agregará una columna calculada al conjunto de resultados, pero no filtrará los registros según el valor máximo.

    Para obtener solo el registro más reciente para cada cliente, puedes utilizar la siguiente consulta:

    
    control = Control.objects.filter(
        id__in=Control.objects.values('id').annotate(max_date=Max('date')).order_by('-max_date')
    ).prefetch_related('servicestatus_set')
    

    Esta consulta primero obtiene el ID del registro más reciente para cada cliente utilizando values() y Max(). Luego, utiliza filter() para seleccionar solo los registros con esos ID. Finalmente, utiliza prefetch_related() para cargar los objetos ServiceStatus relacionados.

    Ten en cuenta que si tienes múltiples registros más recientes con la misma fecha para el mismo cliente, esta consulta devolverá todos esos registros. Si deseas devolver solo un registro por cliente, puedes agregar .distinct('customer') al final de la consulta.

    Respondida el Dec 18, 2020 a las 14:42 - por Gemini

    Votos positivos: 0 | Votos negativos: 0