嵌套Django Rest序列化程序所需的字段

时间:2016-05-23 14:55:52

标签: django django-rest-framework

我有以下结构:

模型

class Customer(models.Model):
    name = models.ForeignKey(Candidate)
    candidate_test = models.ForeignKey(CandidateTest, null=True)
    # Other fields

class Candidate(models.Model):
    first_name = models.CharField(max_length=40)
    # Other fields

class CandidateTest(models.Model):
    test_id = models.ForeignKey(Test)
    # 2 more fields with Foreign Key and null, blank both are True

class Test(models.Model):
    test_name = models.CharField()
    # 2 more fields with Foreign Key and null, blank both are True

串行器

class CandidateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Candidate
        fields = ('first_name', # other fields)


class TestSerializer(serializers.ModelSerializer):
    class Meta:
        model = Test
        fields = ('id', 'test_name',)


class CandidateTestSerializer(serializers.ModelSerializer):
    test_id = TestSerializer()

    class Meta:
        model = CandidateTest
        fields = ('id', 'test_id')


class CustomerSerializer(serializers.ModelSerializer):
    name = CandidateSerializer()
    candidate_test = CandidateTestSerializer()

    class Meta:
        model = Customer
        fields = ('id', 'name', 'candidate_test')

现在,当我使用Django Rest Framework的可浏览API提交(POST)表单时,我收到以下错误:

'list' object has no attribute 'get'

以下是stacktrace:

Error during template rendering

In template /srv/www/safe/shared/env/local/lib/python2.7/site-packages    /rest_framework/templates/rest_framework/horizontal/fieldset.html, error at line 11
'list' object has no attribute 'get'
1   {% load rest_framework %}
2   <fieldset>
3     {% if field.label %}
4       <div class="form-group" style="border-bottom: 1px solid #e5e5e5">
5         <legend class="control-label col-sm-2 {% if style.hide_label %}sr-only{% endif %}" style="border-bottom: 0">
6           {{ field.label }}
7         </legend>
8       </div>
9     {% endif %}
10  
11  

  {% for nested_field in field %}



12      {% if not nested_field.read_only %}
13        {% render_field nested_field style=style %}
14      {% endif %}
15    {% endfor %}
16  </fieldset>
17  
Traceback Switch to copy-and-paste view

/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/core/handlers/base.py in get_response

                                response = response.render()

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/response.py in render

                            self.content = self.rendered_content

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/rest_framework/response.py in rendered_content

                        ret = renderer.render(self.data, media_type, context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/rest_framework/renderers.py in render

                        context = self.get_context(data, accepted_media_type, renderer_context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/rest_framework/renderers.py in get_context

                            'post_form': self.get_rendered_html_form(data, view, 'POST', request),

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/rest_framework/renderers.py in get_rendered_html_form

                                    [('template', 'rest_framework/api_form.html')]

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/rest_framework/renderers.py in render

                        return template.render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/backends/django.py in render

                        return self.template.render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/base.py in render

                                    return self._render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/base.py in _render

                        return self.nodelist.render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/base.py in render

                                bit = self.render_node(node, context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/debug.py in render_node

                            return node.render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/defaulttags.py in render

                                            nodelist.append(node.render(context))

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/defaulttags.py in render

                                return nodelist.render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/base.py in render

                                bit = self.render_node(node, context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/debug.py in render_node

                            return node.render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/base.py in render

                                    return func(*resolved_args, **resolved_kwargs)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/rest_framework/templatetags/rest_framework.py in render_field

                    return renderer.render_field(field, style)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/rest_framework/renderers.py in render_field

                        return template.render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/backends/django.py in render

                        return self.template.render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/base.py in render

                                    return self._render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/base.py in _render

                        return self.nodelist.render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/base.py in render

                                bit = self.render_node(node, context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/debug.py in render_node

                            return node.render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/defaulttags.py in render

                                            nodelist.append(node.render(context))

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/defaulttags.py in render

                                return nodelist.render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/base.py in render

                                bit = self.render_node(node, context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/debug.py in render_node

                            return node.render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/base.py in render

                                    return func(*resolved_args, **resolved_kwargs)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/rest_framework/templatetags/rest_framework.py in render_field

                    return renderer.render_field(field, style)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/rest_framework/renderers.py in render_field

                        return template.render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/backends/django.py in render

                        return self.template.render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/base.py in render

                                    return self._render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/base.py in _render

                        return self.nodelist.render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/base.py in render

                                bit = self.render_node(node, context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/debug.py in render_node

                            return node.render(context)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/django/template/defaulttags.py in render

                                values = list(values)

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/rest_framework/utils/serializer_helpers.py in __iter__

                            yield self[field.field_name]

     ...
▶ Local vars
/srv/www/safe/shared/env/local/lib/python2.7/site-packages/rest_framework/utils/serializer_helpers.py in __getitem__

                        error = self.errors.get(key) if self.errors else None

     ...
▼ Local vars
Variable    Value
field   

IntegerField(label='ID', read_only=True)

self    

<NestedBoundField value={} errors=[u'This field is required.']>

key     

'id'

value   

None

另请注意,使用请求可以正常工作......

2 个答案:

答案 0 :(得分:1)

这是rest框架中的一个错误,它仍然没有修复: https://github.com/tomchristie/django-rest-framework/issues/4073

要解决这个问题,我到目前为止唯一想到的方法是:

继承自ModelSerializerSerializer的班级中的

,覆盖__getitem__方法:

def __getitem__(self, key):
    field = self.fields[key]
    value = self.data.get(key)
    error = self.errors.get(key) if hasattr(self, '_errors') else None
    if isinstance(field, serializers.Serializer):
        return NestedBoundField(field, value, field.data)
    return BoundField(field, value, error)

它会传递field.data而不是错误,可能会导致一些进一步的问题,但到目前为止它比将错误传递为列表更好(嵌套的序列化程序希望错误树完全填充,但它接收父级而是错误信息)

答案 1 :(得分:0)

您的CustomerSerializer序列化程序中有拼写错误:

candidate_test = CustomerSerializer()

应该是:

candidate_test = CandidateTestSerializer()