Tengo el siguiente esquema con PostgreSQL.
class Video(models.Model): title = models.CharField(max_length=255) created_at = models.DateTimeField() disabled = models.BooleanField(default=False) view_count = DecimalField(max_digits=10, decimal_places=0) class TopVideo(models.Model): videos = (Video, on_delete=models.CASCADE, primary_key=True) class Comment(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) video = models.ForeignKey(Video, related_name="comments", on_delete=models.CASCADE)
La razón por la que tengo un modelo de TopVideo es porque tengo millones de videos y consultarlos lleva mucho tiempo en un servidor barato, por lo que tengo un modelo secundario que se llena con una tarea de apio y se vacía y se vuelve a llenar en cada ejecución. lo que hace que el tiempo de carga de la página de inicio sea mucho más rápido. La tarea ejecuta la consulta que ve a continuación y la guarda en el modelo de TopVideo. De esta manera, la tarea puede tardar mucho en ejecutarse, pero el usuario ya no tiene que esperar por la costosa consulta.
Antes de tener el modelo TopVideo, ejecuté esta consulta para mi página de inicio:
videos = ( Video.objects.filter(created_at__range=[start, end]) .annotate(comment_count=Count("comments")) .exclude(disabled=True) .order_by("-view_count")[:100] )
Esto funcionó perfectamente y tuve acceso a "comment_count" en mi plantilla, donde podía mostrar fácilmente la cantidad de comentarios que tenía cada video.
Pero ahora que hago esta consulta:
top_videos = ( TopVideo.objects.all().annotate(comment_count=Count("video__comments")) .select_related("video") .order_by("-video__view_count")[:100] )
y con un bucle for simple,
videos = [] for video in top_videos: videos.append(video.video)
Envío los videos a la plantilla para renderizar. Mi problema es que ya no tengo acceso a "comment_count" dentro de la plantilla, y naturalmente así; Ya no envío el conjunto de consultas. ¿Cómo puedo acceder ahora a comment_count?
Cosas que probé:
Puede configurar el .comment_count
para sus objetos Video
con:
videos = [] for top_video in top_videos: video = top_video.video video .comment_count = top_video.comment_count videos.append(video)
pero dicho esto, no me queda claro por qué está consultando con TopVideo
si básicamente elimina el contexto de TopVideo
del video.
Si desea obtener los Video
s para los que existe un objeto TopVideo
, puede trabajar con:
videos = Video.objects.filter( created_at__range=[start, end] , topvideo__isnull=False ).annotate( comment_count=Count('comments') ).exclude(disabled=True).order_by('-view_count')[:100]
Por lo tanto, topvideo__isnull=False
filtrará los Video
que no sean TopVideo
.