Предварительные условия:
- Queryset должен возвращать
Article
s - Queryset должен возвращать уникальные объекты
- Не должен использоваться дляциклы, попадающие в базу данных (то есть N запросов на N объектов для аннотирования)
мои модели:
class Report(BaseModel):
ios_report = JSONField()
android_report = JSONField()
class Article(BaseModel):
internal_id = models.IntegerField(unique=True)
title = models.CharField(max_length=500)
short_title = models.CharField(max_length=500)
picture_url = models.URLField()
published_date = models.DateField()
clip_link = models.URLField()
reports = models.ManyToManyField(
"Report", through="ArticleInReport", related_name="articles"
)
class ArticleInReport(BaseModel):
article = models.ForeignKey("core.Article", on_delete=models.CASCADE, related_name='articleinreports')
report = models.ForeignKey("core.Report", on_delete=models.CASCADE, related_name='articleinreports')
ios_views = models.IntegerField()
android_views = models.IntegerField()
@property
def total_views(self):
return self.ios_views + self.android_views
Все начинается с объекта Report
это создается через установленные интервалы.Этот отчет содержит данные о статьях и их соответствующих просмотров.Report
будет иметь отношение с Article
до ArticleInReport
, которое содержит общее число пользователей в Article
на момент импорта отчета .
ВНа мой взгляд, мне нужно отобразить следующую информацию:
- Все статьи, которые получили просмотры за последние 30 минут.
- Каждая статья помечена следующей информацией, и это гдеЯ сталкиваюсь с проблемой:
Если присутствует, количество просмотров объекта Article
в last Report
.Если нет, то 0.
мой views.py
файл:
reports_in_time_range = Report.objects.filter(created_date__range=[starting_range, right_now]).order_by('created_date')
last_report = reports_in_time_range.prefetch_related('articles').last()
unique_articles = Article.objects.filter(articleinreports__report__in=reports_in_time_range).distinct('id')
articles = Article.objects.filter(id__in=unique_articles).distinct('id').annotate(
total_views=Case(
When(id__in=last_report.articles.values_list('id', flat=True),
then=F('articleinreports__ios_views') + F('articleinreports__android_views')),
default=0, output_field=IntegerField(),
))
Некоторые объяснения моего мыслительного процесса: во-первых, получите мне только статьи, которыепоявляются в соответствующих отчетах за промежуток времени (filter(id__in=unique_articles)
), возвращают только отдельные статьи.Затем, если идентификатор статьи появляется в списке статей последний отчет (конечно, через ArticleInReport
), рассчитайте количество просмотров iOS + Android для этого ArticleInReport
.
Thisвышеупомянутая аннотация работает в течение большинства Article
с, но с треском проваливается для других без видимой причины.Я пробовал много разных подходов, но, похоже, всегда получаю неправильные результаты.