django django-queryset django-orm django-1.8

Haga una anotación con el valor de la última relacionada en Django 1.8 utilizando la anotación condicional



django-queryset django-orm (4)

Algo como esto puede funcionar para usted:

Tengo esto para mostrar la última reserva para restaurantes.

Reservation.objects.filter( restaurant__city_id__gt=0 ).distinct().annotate(city_count=Count( ''restaurant_id'') ).order_by(''-reservationdate'').filter(city_count__gte=1)[:20]

En tu caso puede ser algo como:

city = Census.objects.filter( city_id__gt=0 ).distinct().annotate(city_count=Count( ''city_id'') ).order_by(''-date'').filter(city_count__gte=1)[:20]

y tu html

{% for city in city %} {{ city.city.name }} {{ city.date }}<br> {% endfor %}

Tengo los siguientes modelos:

class City(models.Model): ... class Census(models.Model): city = models.ForeignKey(City) date = models.DateTimeField() value = models.BigIntegerField()

Ahora me gustaría anotar una ciudad-queryset con el valor del último Censo. ¿Cómo logro eso?

Yo he tratado:

City.objects.annotate(population=Max(''census__date'')) # --> annotates date and not value City.objects.annotate(population=Max(''census__value'')) # --> annotates highest value, not latest City.objects.annotate(population= Case( When( census__date=Max(''census__date''), then=''census__value'') ) ) # --> annotates ''None'' City.objects.annotate(population= Case( When( census__date=Max(''census__date''), then=''census__value'') ), output_field=BigIntegerField() ) # --> takes forever (not sure what happens at the end, after some minutes I stopped waiting)

Cualquier ayuda muy apreciada!


En este momento, no son una expresión de consulta de django para anotar un campo no agregado de un modelo 1: N relacionado basado en un sql que tiene expresión.

Puede lograrlo con varias soluciones alternativas como la consulta dividida y trabajar con datos en la memoria (itertools groupby fe) o mediante consultas sin formato. Pero esto no coincidirá con el rendimiento de sus requisitos y el agnóstico de la base de datos .

Explico aquí qué haré si esta fuera mi aplicación. Para los desarrolladores es difícil tener redundancia en la base de datos. En su escenario, el último census por city es un campo calculado ... pero, en este caso, considere materializar el last_census :

El trabajo sucio ...

class City(models.Model): last_census = models.ForeignKey(''Census'', null=True, blank=True, editable=False) ...

Para facilitar el mantenimiento, puede sobrescribir los métodos de save y delete en el Census para mantener last_census el last_census .

class Census(models.Model): ... #overriding save def save(self, *args, **kwargs): super(Census, self).save(*args, **kwargs) #updating last_census on referenced city max_census = Census.objects.filter( city = self.city ).latest(''date'') self.city.last_census = max_census.city if max_census else None self.city.save() #overriding delete def delete(self, *args, **kwargs): #updating last_census on referenced city max_census = ( Census.objects .filter( city = self.city ) .exclude( id = self.id ) .latest(''date'') ) self.city.last_census = max_census.city if max_census else None self.city.save() super(Census, self).delete(*args, **kwargs)

Aviso: si está más cómodo, puede codificarlo con señales (pre_delete, post_save, ...) en lugar de anular los métodos.

El mejor ...

Su consulta ahora:

City.objects.select_related(''last_census__value'').all()


Es tarde y tengo hambre, así que veo que esto no llegará hasta el final *, pero el siguiente código devolverá el último valor de censo en un conjunto de valores para una ciudad determinada. Un queryset podría ser posible, pero otra vez tengo hambre!

* No estaba seguro de si necesitaba recuperar todos los valores más recientes para todas las ciudades o una ciudad específica. Lo último es bastante fácil, lo primero es un poco más difícil. Fácilmente puede poner esto como un método en su modelo y llamarlo a cada ciudad en un bucle dentro de una plantilla / vista.

¡Espero que esto ayude!

from app.models import * from django.db.models import F City.objects.annotate( values=F("census__value"), date=F("census__date"))/ .values(''values'', ''name'').filter(name="Atlanta")/ .latest(''date'')


También he tenido un problema en el que necesito un objeto de valor máximo de un conjunto relacionado, pero necesito el objeto completo. No he podido encontrar una solución usando la anotación y el caso. Hasta que lo haga, uso esta solución de búsqueda previa. Si cada ciudad no tiene una gran cantidad de objetos censales, o si su solicitud no tiene un límite de rendimiento, esto puede funcionar para usted.

inner_qs = Census.objects.order_by(''-date'') cities = City.objects.prefetch_related(Prefetch("census_set", queryset=inner_qs, to_attr="census_list")) class City(models.Model): @property def latest_census(self): if hasattr(self, ''census_list'') and len(self.census_list) > 0: return self.census_list[0] return None

Si esto no funciona para usted, considere algunas de las sugerencias que se encuentran aquí: http://blog.roseman.org.uk/2010/08/14/getting-related-item-aggregate/