所有
我有2个模型通过外键链接在一起。我在反向字段上使用自定义相关管理器。
models.py:
class Foo(models.Model):
name = models.CharField(max_length=23)
bar = models.ForeignKey("Bar", related_name="foos")
class Bar(models.Model):
name = models.CharField(max_length=42)
my_custom_manager = MyCustomManager()
class MyCustomManager(models.Manager):
use_for_related_fields = True
def get_queryset(self):
if self.instance.is_special():
return do_something_special() # returns a list of Foos
return super(MyCustomManager, self).get_queryset()
要使用此功能,请使用以下代码:
my_bar_instance.foos.add(my_foo_instance)
my_bar_instance.foos(manager="my_custom_manager").all()
我知道这是一个人为的例子,但请相信我有时候在向这个字段添加对象时我需要做非标准的事情。无论如何,这段代码运行正常。问题是当我尝试序列化它时。
serializers.py:
class FoosField(serializers.RelatedField):
queryset = Foo.objects.all()
list_serializer_class = ListSerializer
def to_representation(self, value):
if not value:
return {}
from .some_other_package import FooSerializer
serializezr = FooSerializer()
representation = serializezr.to_representation(value)
return representation
def to_internal_value(self, data):
if not data:
return None
from .some_other_package import FooSerializer
serializer = FooSerializer()
internal_value = serializer.to_internal_value(data)
return internal_value
class BarSerializer(ModelSerializer):
class Meta:
model = Bar
fields = (
'id',
'name',
'foos',
)
foos = BarField(many=True, required=False, allow_null=True, queryset=Foo.objects.all())
它只输出“foos”字段的空列表。我怀疑这是因为它直接调用反向关系字段foos
而不是指定自定义管理器foos(manager="my_custom_manager")
。关于如何告诉Django Rest Framework使用自定义管理器的任何想法?
由于
答案 0 :(得分:1)
使用SerializerMethodField定义一个函数,您可以在其中处理所需的查询集。例如,另请参见this question。
答案 1 :(得分:0)
可以做到。但这很难看:
<强> serializers.py:强>
class FoosChildField(ManyRelatedField):
def get_attribute(self, instance):
manager = self.child_relation.manager
if manager:
relationship = getattr(instance, manager.get_name())
return relationship.all() if (hasattr(relationship, 'all')) else relationship
super(FoosChildField, self).get_attribute(instance)
class FoosField(serializers.RelatedField):
queryset = Foo.objects.all()
list_serializer_class = ListSerializer
def __init__(self, **kwargs):
manager = kwargs.pop("manager", None)
super(FoosField, self).__init__(**kwargs)
self.manager = manager
@classmethod
def many_init(cls, *args, **kwargs):
list_kwargs = {'child_relation': cls(*args, **kwargs)}
for key in kwargs.keys():
if key in MANY_RELATION_KWARGS:
list_kwargs[key] = kwargs[key]
return FoosChildField(**list_kwargs)
def to_representation(self, value):
if not value:
return {}
from .some_other_package import FooSerializer
serializezr = FooSerializer()
representation = serializezr.to_representation(value)
return representation
def to_internal_value(self, data):
if not data:
return None
from .some_other_package import FooSerializer
serializer = FooSerializer()
internal_value = serializer.to_internal_value(data)
return internal_value
class BarSerializer(ModelSerializer):
class Meta:
model = Bar
fields = (
'id',
'name',
'foos',
)
foos = BarField(many=True, required=False, allow_null=True, queryset=Foo.objects.all(), manager=Bar.my_custom_manager)
我添加了一个新课程(FoosChildField
)和两个新方法(__init__
&amp; many_init
)。
基本上,我将管理器传递给DRF相关的字段实例,后者又将其传递给DRF“子”字段(因为这是一个列表序列化器)。 get_attribute
fn使用该经理获取实际值。
呸。