我试图根据父记录只预取最新的记录。在
我的模特就是这样
class LinkTargets(models.Model):
device_circuit_subnet = models.ForeignKey(DeviceCircuitSubnets, verbose_name="Device", on_delete=models.PROTECT)
interface_index = models.CharField(max_length=100, verbose_name='Interface index (SNMP)', blank=True, null=True)
get_bgp = models.BooleanField(default=False, verbose_name="get BGP Data?")
dashboard = models.BooleanField(default=False, verbose_name="Display on monitoring dashboard?")
class LinkData(models.Model):
link_target = models.ForeignKey(LinkTargets, verbose_name="Link Target", on_delete=models.PROTECT)
interface_description = models.CharField(max_length=200, verbose_name='Interface Description', blank=True, null=True)
...
以下查询因错误而失败
^{pr2}$查询:
link_data = LinkTargets.objects.filter(dashboard=True) \
.prefetch_related(
Prefetch(
'linkdata_set',
queryset=LinkData.objects.all().order_by('-id')[0]
)
)
我想改为获取LinkData并做一个select相关的操作,但是我不知道如何为每个link_target_id获取1条记录
link_data = LinkData.objects.filter(link_target__dashboard=True) \
.select_related('link_target')..?
编辑:
使用rtindru的解决方案,pre-fetch似乎是空的。其中目前有6条记录,3条链接目标的每条记录各1条
>>> link_data[0]
<LinkTargets: LinkTargets object>
>>> link_data[0].linkdata_set.all()
<QuerySet []>
>>>
LinkData.objects.all().order_by('-id')[0]
不是查询集,它是模型对象,因此出现错误。在您可以尝试
LinkData.objects.all().order_by('-id')[0:1]
,这确实是一个查询集,但它行不通。给定prefetch_related
的工作方式,queryset参数必须返回一个包含所需的所有LinkData
记录的queryset(然后进一步过滤,其中的项与LinkTarget对象连接起来)。这个查询集只包含一个项,所以这是不好的。(Django会抱怨“一旦获取了一个片段就无法过滤查询”,并引发了一个异常,因为它应该这样做)。在我们退后。实际上,你在问一个聚合/注释问题——对于每个LinkTarget,你想知道最新的LinkData对象,或者“id”列的“max”。最简单的方法是只使用id进行注释,然后进行单独的查询以获取所有对象。在
因此,它应该是这样的(我在我的项目中使用了一个类似的模型,所以它应该可以工作,但是下面的代码可能有一些错误):
我故意不将其放入一个预取中,屏蔽
linkdata_set
,因为结果是你有欺骗你的对象,linkdata_set
属性现在缺少结果。你真的想被它咬下去吗?最好创建一个新的属性,它正好拥有你想要的东西。在原因是
Prefetch
需要一个DjangoQueryset
作为queryset
参数,而您给出的是一个对象的实例。在按如下方式更改查询:
这确实有一个不幸的结果,即在很大程度上取消了{}的目的。在
更新 此操作只全局预取一条记录;而不是每个
LinkTarget
最新的LinkData
记录。在要预取每个LinkTarget的max LinkData,您应该从LinkData开始:可以按如下方式实现:
LinkData.objects.filter(link_target__dashboard=True).values('link_target').annotate(max_id=Max('id'))
这将返回一个{{}:12、
max_id
:3223}的字典然后可以使用它返回正确的对象集;也许可以根据
max_id
的值过滤LinkData。在看起来像这样:
^{pr2}$相关问题 更多 >
编程相关推荐