我有一个模型,其中需要几个特定字段的历史数据,所以我将这些字段放入一个具有外键关系的单独模型中。
有点像这样:
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进行查询,但如果可能的话,我真的希望避免使用原始SQL。
此解决方案使用了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
字段的好名称。
您可以通过查询DataThing
同时引用DataThingHistory
:来执行同样的操作
search_results = DataThing.objects.filter(datathinghistory__text_with_history__icontains=searchterm)
查看django文档,了解如何查询反向关系。
编辑:
我以前的回答不完整。为了搜索每个DataThing
的最新历史记录,您需要使用Max
:在时间戳上搜索annotate
from django.db.models import Max
search_results = search_results.values('field1', 'field2',...).annotate(latest_history=Max('datathinghistory__timestemp'))
这不会为您提供完整的DataThing
对象,但您可以根据需要向values
添加任意多的字段。