Django 复杂注释

标签 django django-orm

先决条件:

  • 查询集必须返回文章
  • 查询集必须返回唯一的对象
  • 不得使用访问数据库的 for 循环(意味着对要注释的 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会通过ArticleInReportArticle建立关系,其中保存了Article中的用户总数< strong>导入报告时。

在我看来,我需要显示以下信息:

  • 过去 30 分钟内获得浏览的所有文章。
  • 每篇文章都注释有以下信息,这就是我面临的问题:

If present, the number of views the Article object had in the last Report. If not present, 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)),仅返回不同的文章。接下来,如果文章的 ID 出现在最后报告的文章列表中(当然是通过 ArticleInReport),则计算该 ArticleInReport< 的 iOS 浏览量 + Android 浏览量.

上面的注释适用于大多数文章,但对于其他文章却无缘无故地失败了。我尝试了许多不同的方法,但似乎总是得到错误的结果。

最佳答案

避免数据库命中非常重要,但不是以这个价格。在我看来,您应该将查询拆分为两个或多个查询。拆分查询将提高可读性,也可能提高性能(有时两个简单查询比一个复杂查询运行得更快)。请记住,您拥有 dic、理解和 itertools 的所有功能来处理部分结果。

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()

report_articles_ids = ( Article
                       .objects
                       .filter(articleinreports__report=last_report)
                       .values_list('id', flat=True)
                       .distinct())

report_articles = ( Article
                   .objects
                   .filter(id__in=report_articles_ids)
                   .annotate( total_views=Sum(  
                                   F('articleinreports__ios_views') +
                                   F('articleinreports__android_views'),
                                   output_field=IntegerField()
                   )))

other_articles = ( Article
                   .objects
                   .exclude(id__in=report_articles_ids)
                   .annotate( total_views=ExpressionWrapper(
                                    Value(0),
                                    output_field=IntegerField())
                   )))

articles = report_articles | other_articles

关于Django 复杂注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52689949/

相关文章:

python - 方法不允许(POST)Django 405 错误

python - Django 模板中的动态列数

python - 通过计算在 django 中批量更新

python - 在django中确定属性是否为 `DeferredAttribute`

django - 不支持的 CharField 查找 'lower' 或不允许加入该字段

python - Django ORM : get objects distinct on a column and ordered by another column

sql - Django 中 GROUP BY 注释的聚合

python - 为什么在 pytest-django 中使用 ThreadPoolExecutor 时会得到空的 django 查询集?

python - Django:属性错误: "Object has no attribute"

python - 我可以使用 python-django 框架开发 Web 应用程序并将其作为桌面应用程序运行吗?