I have a question concerning using proxy models with the Django Rest Framework and nested serialization.
My proxy models are as follows:
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
The Field model is defined in another app that I've included in my project. I wanted to add my own method to it without modifying the model so I made a proxy.
These are the serializers for the proxy models:
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')
And the 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)
If I go to /fields/ it works fine. The method I added in the proxy model is executed correctly.
[
{
"url": "http://127.0.0.1:8000/fields/1/",
"field_type": "the result",
},
{ ...
But if I go to /forms/ I get the following error:
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>
As you can see the obj is Field instead of MyField which is why it's not able to call field_type_name. This only happens on the nested serialization. If anyone has a suggestion on how I can best fix this I'd greatly appreciate it.
EDIT:
Based on Kevin's response I'm editing the proxy models to try to fix this.
Here are the base models for reference:
class Form(AbstractForm):
pass
class Field(AbstractField):
form = models.ForeignKey("Form", related_name="fields")
Here is my attempt to fix the problem (using examples from 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
Now I can get MyForm from MyField but not MyField from MyForm (the reverse):
>>> MyField.objects.get(pk=1).form
<MyForm: Cool Form>
>>> MyForm.objects.get(pk=1).fields.all()
[]
I