我有一个关于将代理模型与Django Rest Framework和嵌套序列化一起使用的问题。
我的代理模型如下:
class MyField(Field):
class Meta:
proxy = True
def field_type_name(self):
# logic that computes the field type name here
return "the result"
class MyForm(Form):
class Meta:
proxy = True
Field模型在我已包含在项目中的另一个应用程序中定义。我想在不修改模型的情况下添加自己的方法,因此我创建了一个代理。
这些是代理模型的序列化程序:
class MyFieldSerializer(serializers.HyperlinkedModelSerializer):
field_type = serializers.ChoiceField(source='field_type_name',
choices=form_fields.NAMES)
class Meta:
model = MyField
fields = ('url', 'field_type',)
class MyFormSerializer(serializers.HyperlinkedModelSerializer):
fields = MyFieldSerializer(many=True)
class Meta:
model = MyForm
fields = ('url', 'fields')
和viewsets:
class MyFieldViewSet(viewsets.ModelViewSet):
queryset = MyField.objects.all()
serializer_class = MyFieldSerializer
class MyFormViewSet(viewsets.ModelViewSet):
queryset = MyForm.objects.all()
serializer_class = MyFormSerializer
urls.py:
router.register(r'fields', views.MyFieldViewSet)
router.register(r'forms', views.MyFormViewSet)
如果我去/ fields /它工作正常。我在代理模型中添加的方法正确执行。
[
{
"url": "http://127.0.0.1:8000/fields/1/",
"field_type": "the result",
},
{ ...
但是如果我去/ forms /我会收到以下错误:
AttributeError at /forms/
'Field' object has no attribute 'field_type_name'
/Users/..../lib/python2.7/site-packages/rest_framework/fields.py in get_component
"""
Given an object, and an attribute name,
return that attribute on the object.
"""
if isinstance(obj, dict):
val = obj.get(attr_name)
else:
**val = getattr(obj, attr_name)**
if is_simple_callable(val):
return val()
return val
▼ Local vars
Variable Value
attr_name u'field_type_name'
obj <Field: Cools2>
正如您所看到的,obj是Field而不是MyField,这就是为什么它无法调用field_type_name。这只发生在嵌套序列化上。如果有人建议如何最好地解决这个问题,我会非常感激。
编辑:
基于Kevin的回复,我正在编辑代理模型以尝试修复此问题。
以下是参考的基本模型:
class Form(AbstractForm):
pass
class Field(AbstractField):
form = models.ForeignKey("Form", related_name="fields")
以下是我尝试解决问题(使用Django proxy model and ForeignKey中的示例):
class MyField(Field):
class Meta:
proxy = True
def field_type_name(self):
# logic that computes the field type name here
return "the result"
# this works
@property
def form(self):
return MyForm.objects.get(id=self.form_id)
class MyForm(Form):
class Meta:
proxy = True
# this does not work
@property
def fields(self):
qs = super(MyForm, self).fields
qs.model = MyField
return qs
现在我可以从MyField获取MyForm,但不能从MyForm获取MyField(反之):
>>> MyField.objects.get(pk=1).form
<MyForm: Cool Form>
>>> MyForm.objects.get(pk=1).fields.all()
[]
我
答案 0 :(得分:0)
这是因为当您访问表单上的Form
属性时,您的模型MyForm
(或MyField
)未配置为返回field
个对象。它未配置为替换您的代理版本。
亲自试用,打开./manage.py shell
并尝试阅读fields
相关管理员,它会返回Field
个对象的集合。
>>> form = MyForm.objects.all()[0].fields.all()
(顺便说一句,我必须猜测实际的模型结构,因为原始Field
和Form
模型未包含在您的示例中。
如果它是只读字段,您可以使用serializers.SerializerMethodField
向序列化程序添加方法(您的field_type_name()
。如果您希望能够编辑它,那么您最好不要写您自己的字段子类,用于处理转换。