Discussion:
[pyar] [Django] exclusion Related name
Daniel
2018-11-28 00:38:04 UTC
Permalink
Hola gente linda:

Dado el modelo Prestamos, ¿cómo puedo hacer para que me limite la lista en
el related name a los que NO estan en préstamos? No se como usar
Libro.prestados.all() porque tengo que buscar en todos los libros y no en
uno. ¿alguna forma pythonezca que sugieran?

class Prestamo(models.Model):
"""
Registra cada evento de préstamo de libros
"""
fecha_prestamo = models.DateTimeField(auto_now_add=True, verbose_name="Fecha
de Retiro")
persona = models.ForeignKey(Lector, on_delete=models.CASCADE)
libro = models.ForeignKey(Libro, related_name="prestados", on_delete=
models.CASCADE)
fecha_devuelto = models.DateTimeField(blank=True, null=True,
verbose_name="Fecha
de Devolución")
observaciones = models.TextField(blank=True, null=True)
marcos hipe
2018-11-28 01:47:43 UTC
Permalink
Si lo que queres hacer es obtener todos los libros que no tengan uno o mas
Prestamo asociados, podes hacer:
Libro.objects.filter(prestamos__isnull=True)

Si lo que queres es obtener todos los que no tengan un prestamo "Activo" (o
sea, que no haya sido devuelto), entonces:
Libro.objects.\
annotate(prestamos_activos=Count('prestamos',
filter=Q(prestamos__fecha_devuelto__isnull=True))).\
filter(prestamos_activos=0)

para entender el annotate, lo que hace es agregar una columna (si lo vemos
como tabla sql) o un campo (field), para cada fila (o objeto). Esta columna
representa el numero de prestamos activos (o sea, que no fueron devueltos,
o sea, que tienen fecha_devuelto = None). Despues podemos usar esa columna
para filtrar, en este caso, queremos todos los libros que no tengan ningun
prestamo_activo.
Observacion: No lo probe, asi que puede haber algun error. y tambien podria
pasar que los libros que no tienen prestamos, en vez de tener un 0 en
"prestamos_activos" tengan un None, si es asi, habria que agregar ese caso
en el filtro (con un OR, asi que hay que usar el Q(...) | Q(...))
Post by Daniel
Dado el modelo Prestamos, ¿cómo puedo hacer para que me limite la lista en
el related name a los que NO estan en préstamos? No se como usar
Libro.prestados.all() porque tengo que buscar en todos los libros y no en
uno. ¿alguna forma pythonezca que sugieran?
"""
Registra cada evento de préstamo de libros
"""
fecha_prestamo = models.DateTimeField(auto_now_add=True, verbose_name="Fecha
de Retiro")
persona = models.ForeignKey(Lector, on_delete=models.CASCADE)
libro = models.ForeignKey(Libro, related_name="prestados", on_delete=
models.CASCADE)
fecha_devuelto = models.DateTimeField(blank=True, null=True, verbose_name="Fecha
de Devolución")
observaciones = models.TextField(blank=True, null=True)
_______________________________________________
Sitio web: http://www.python.org.ar/
Para administrar la lista (o desuscribirse) entrar a
http://listas.python.org.ar/listinfo/pyar
La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de
Argentina - http://www.usla.org.ar
Daniel
2018-11-29 11:41:08 UTC
Permalink
Respondo con la solución por si a alguien se enfrenta a algo similar
(Gracias Marcos!!!)
Post by marcos hipe
Si lo que queres hacer es obtener todos los libros que no tengan uno o mas
Libro.objects.filter(prestamos__isnull=True)
Si lo que queres es obtener todos los que no tengan un prestamo "Activo"
Libro.objects.\
annotate(prestamos_activos=Count('prestamos',
filter=Q(prestamos__fecha_devuelto__isnull=True))).\
filter(prestamos_activos=0)
para entender el annotate, lo que hace es agregar una columna (si lo vemos
como tabla sql) o un campo (field), para cada fila (o objeto). Esta columna
representa el numero de prestamos activos (o sea, que no fueron devueltos,
o sea, que tienen fecha_devuelto = None). Despues podemos usar esa columna
para filtrar, en este caso, queremos todos los libros que no tengan ningun
prestamo_activo.
Observacion: No lo probe, asi que puede haber algun error. y tambien
podria pasar que los libros que no tienen prestamos, en vez de tener un 0
en "prestamos_activos" tengan un None, si es asi, habria que agregar ese
caso en el filtro (con un OR, asi que hay que usar el Q(...) | Q(...))
La solución que marcos propuso me anduvo a la perfección
*Libros disponibles:*
Libro.objects.annotate(prestamos_activos=Count('prestados',
filter=Q(prestados__fecha_devuelto__isnull=True)
...: )).filter(prestamos_activos=0)
*Libros Prestados:*
Libro.objects.annotate(prestamos_activos=Count('prestados',
filter=Q(prestados__fecha_devuelto__isnull=True)
...: )).filter(prestamos_activos__gt=0)

Estoy usando autocompletar, asi que le dejo tarea para otro probar el
*limit_choice_to*

Rafael E. Ferrero
2018-11-28 14:21:19 UTC
Permalink
Post by Daniel
Dado el modelo Prestamos, ¿cómo puedo hacer para que me limite la lista en
el related name a los que NO estan en préstamos? No se como usar
Libro.prestados.all() porque tengo que buscar en todos los libros y no en
uno. ¿alguna forma pythonezca que sugieran?
"""
Registra cada evento de préstamo de libros
"""
fecha_prestamo = models.DateTimeField(auto_now_add=True, verbose_name="Fecha
de Retiro")
persona = models.ForeignKey(Lector, on_delete=models.CASCADE)
libro = models.ForeignKey(Libro, related_name="prestados", on_delete=
models.CASCADE)
fecha_devuelto = models.DateTimeField(blank=True, null=True, verbose_name="Fecha
de Devolución")
observaciones = models.TextField(blank=True, null=True)
_______________________________________________
Buen día y ¿usar un manager
<https://docs.djangoproject.com/es/2.1/topics/db/managers/>para este tipo
de consultas no te sirve?
Loading...