序列化程序如何检索反向外键引用的列



在事务处理的场景中,我们有:

  • order,用于记录传入事务,以及
  • order_log以记录对记录的订单的更新,表order具有外键

记录的订单在日志上可能有零到多个更新。

我们希望对这两个表进行一个扁平化的视图,就像从order left outer join order_log中选择的SQL查询一样,具有以下行为:

  • 如果订单没有更新,则用空值联合列出订单
  • 如果订单有一次更新,请将订单与更新日志一起列出
  • 如果订单有多个更新,请将订单与每个更新日志一起列出多次

作为下面的示例源代码,我们使用了.prefetch_related('orderlog_set'),它得到了所需的扁平化效果,Django后端日志显示了一个按预期发送到数据库的左外部联接SQL查询。因此,相互关系在上述三个条件下都是正确的。

但是,我们无法在order_item中检索列,因为表的方向与外键相反

串行器FlatOrderLogSerializer的元模型基于表order,因此它通过外键的反向或反向引用表order_log。因此,序列化程序无法检索正确的列,并且总是获取null值。

我们正确地检索了本机表中的列以及外键的法线方向所引用的表。不幸的是,只有反向/反向外键不起作用。

我们是Django这部分的新手,不知道如何正确设置字段对象的source属性。我们尝试了serializers.ReadOnlyField(source='orderlog_set__update_ts', ...和其他一些选项,但到目前为止还没有成功。有关更多详细信息,请参阅示例代码中的注释。

如果您需要更多信息,请告诉我,如有任何建议,我们将不胜感激。

# Table 'order'
class Order(models.Model):
...
# Table 'order_log'
class OrderLog(models.Model):
order = models.ForeignKey('Order')
update_ts = models.DateTimeField(auto_now=True, editable=False, verbose_name="Last Updated On")
...
# The serializer
class FlatOrderLogSerializer(serializers.ModelSerializer):
# Standing at table 'order', it refers to table 'order_log' by a reverse (backward) foreign-key.
# The field with source='orderlog_set__update_ts' always gets null, and
# we tried other source settings, e.g. 'orderlog_set.update_ts', or 'orderlog.update_ts', 
# unfortunately nothing works so far.
update_ts = serializers.ReadOnlyField(source='orderlog_set__update_ts', allow_null=True)
...
class Meta:
model = Order
fields = (
'update_ts',
...
)
# The view
class FlatOrderLogView(generics.ListAPIView):
serializer_class = rest_models.FlatOrderLogSerializer
...
def get_queryset(self):
flat_orderlogs = Order.active_objects.filter(
...
).prefetch_related(
'orderlog_set',
).all()
return flat_orderlogs

经过一些谷歌搜索后,它看起来像:

Django框架提供了一个标准函数select_related(),用于按照外键的正向进行连接。后端将此函数实现为内部联接SQL查询
  • 然而,我们并没有找到一种通过外部连接向后看的优雅方式。相反,大多数文章建议使用函数prefetch_related()并制作嵌套的序列化程序。这种设计模式似乎是一种常见的做法
  • 以下是一些初步想法,我们希望从专家那里得到反馈或更正:

    使用SQL查询,我们可以通过外部联接在外键的向后方向上引用另一个表。然而,Django似乎并不鼓励这种直观的设计模式,因此,没有实现标准的方法。如果得到确认,我们将放弃外部联接查询,转而研究其他解决方案。

    最新更新