Django自定义加载外键

Django customization of loading a foreign key

假设我有三个相关的 类 例如:

class A:
  ...

class B:
  ...
  a = models.ForeignKey(A, ...)

class C:
  ...
  b = models.ForeignKey(B, ...)

我想自定义对 C 对象的 b 访问以立即加载 a。这意味着每当我调用 c.b 时也会调用 select_related 查询调用 a。还有其他场景我需要能够使用 prefetch_related.

我正在使用 django 3.1.1

如果你想用外键重用一些 select_related(),你可以这样做:

from django.db import models
from django.db.models.fields.related_descriptors import ForwardManyToOneDescriptor


class FullBForwardManyToOneDescriptor(ForwardManyToOneDescriptor):
    def get_object(self, instance):
        qs = self.get_queryset(instance=instance).select_related("a")
        # Assuming the database enforces foreign keys, this won't fail.
        return qs.get(self.field.get_reverse_related_filter(instance))


class FullBForeignKey(models.ForeignKey):
    forward_related_accessor_class = FullBForwardManyToOneDescriptor


class C:
  ...
  b = FullBForeignKey(B, ...)

class D:
  ...
  b = FullBForeignKey(B, ...)

class E:
  ...
  b = FullBForeignKey(B, ...)

如果 B 外键有很多用例,您可以为每个用例创建其他 类 继承 ForwardManyToOneDescriptor 和 ForeignKey。

class F:
  ...
  b = SomeExtraBForeignKey(B, ...)

class G:
  ...
  b = SomeExtraBForeignKey(B, ...)