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.

Django select_related() con latest() límite en objeto relacionado.

Considere tener la tabla Table y la tabla Reservation en mi aplicación de restaurante Django.

class Reservation(models.Model):
    table = models.ForeignKey(
        Table,
        on_delete=models.CASCADE,
        blank=False, null=False,
        related_name='reservations'
    )

    def __str__(self):
        return str(self.pk)

class Table(models.Model):
    def __str__(self):
        return str(self.pk)

Si quiero mostrar una lista de mesas de restaurante con su correspondiente reserva, entonces necesito seleccionar la reserva relacionada para cada mesa. Pero necesito seleccionar solo la última reserva de cada mesa (que está activa en este momento).

¿Cómo lograr eso?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para lograr esto, se puede agregar un campo ForeignKey llamado last_reservation en el modelo Table que apunte a la última reserva realizada para esa mesa. Se puede actualizar este campo cada vez que se realiza una nueva reserva para la mesa al anular el método save en el modelo Reservation de la siguiente manera:

    class Reservation(models.Model):
        table = models.ForeignKey(
            Table,
            on_delete=models.CASCADE,
            blank=False, null=False,
            related_name='reservations'
        )
        created_at = models.DateTimeField(auto_now_add=True)
    
        class Meta:
            ordering = ['-created_at']  # ordenar por created_at en orden descendente
    
        def __str__(self):
            return str(self.pk)
    
    class Table(models.Model):
        last_reservation = models.ForeignKey(
            Reservation,
            on_delete=models.SET_NULL,
            blank=True, null=True,
            related_name='last_for_table'
        )
    
        def __str__(self):
            return str(self.pk)
    
        def get_last_reservation(self):
            try:
                reservation = self.reservations.first()
                return reservation if reservation == self.last_reservation else None  # devolver None si last_reservation no es la última reserva real
            except Reservation.DoesNotExist:
                return None
    
        def set_last_reservation(self):
            reservation = self.get_last_reservation()
            self.last_reservation = reservation
            self.save()
    
        def save(self, *args, **kwargs):
            super().save(*args, **kwargs)
            self.set_last_reservation()
    

    Ahora, se puede obtener la lista de mesas con sus últimas reservas correspondientes utilizando el siguiente código:

    tables = Table.objects.prefetch_related('last_reservation').all()
    for table in tables:
        last_reservation = table.last_reservation
        if last_reservation:
            print(f'Mesa {table.pk}: {last_reservation}')
    

    Este código utilizará el método prefetch_related de Django para buscar la última reserva de cada mesa con solo dos consultas: una para buscar todos los objetos de Table y otra para buscar todos los objetos de Reservation para esas mesas.

Comments are closed.