如何通过单独模型中最新相应条目中的文本字段过滤Django查询集

时间:2016-04-14 19:55:14

标签: python django django-models

我有一个模型,我需要几个特定字段的历史数据,因此我将这些字段放入具有外键关系的单独模型中。

有点像这样:

class DataThing(models.Model):
    # a bunch of fields here...


class DataThingHistory(models.Model):
    datathing_id = models.ForeignKey('DataThing', on_delete=models.CASCADE)
    text_with_history = models.CharField(max_length=500, null=True, blank=True)
    # other similar fields...
    timestamp = models.DateTimeField()

现在我正在尝试使用后者最新相应条目中的文本字段来过滤前一个模型。

基本上如果这些不是单独的模型我会尝试这个:

search_results = DataThing.objects.filter(text_with_history__icontains=searchterm)

但是我没有想出一个很好的方法来实现这个一对多的关系,并且只使用后一个模型中最新时间戳的条目,至少使用Django ORM。

我知道如何使用原始SQL进行查询,但我真的希望尽可能避免使用raw。

2 个答案:

答案 0 :(得分:2)

此解决方案使用distinct(*fields),目前只支持Postgres:

latest_things = DataThingHistory.objects.
    order_by('datathing_id_id', '-timestamp').
    distinct('datathing_id_id')

lt_with_searchterm = DataThingHistory.objects.
    filter(id__in=latest_things, text_with_history__icontains=searchterm)

search_results = DataThing.objects.filter(datathinghistory__in=lt_with_searchterm)

这应该导致单个数据库查询。我已将查询拆分为可读性,但您可以将其嵌套到单个语句中。顺便说一句,正如您在此处看到的那样,foo_id不是ForeignKey字段的好名称。

答案 1 :(得分:0)

您可以在引用DataThing时查询DataThingHistory来执行相同操作:

search_results = DataThing.objects.filter(datathinghistory__text_with_history__icontains=searchterm)

how to query on reverse relationship上查看django doc。

修改

我之前的回答是不完整的。要搜索每个DataThing的最新历史记录,您需要annotate使用Max时间戳:

from django.db.models import Max

search_results = search_results.values('field1', 'field2',...).annotate(latest_history=Max('datathinghistory__timestemp'))

这不会为您提供完整的DataThing个对象,但您可以根据需要向values添加任意数量的字段。