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, ...)
假设我有三个相关的 类 例如:
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, ...)