Django Rest Framework可写嵌套序列化器引发AttributeError

时间:2016-04-06 08:47:12

标签: python django django-rest-framework

我正在开发基于Django的货运管理应用程序。我们已经集成了Django Rest Framework并暴露了一些端点。

现在django app叫做#34; port_manager"有以下型号......

models.py

from location.models import CountryList, DistrictList

class PortList(models.Model):
    name = models.CharField(max_length=45)
    countryList_id = models.ForeignKey(CountryList, models.SET_NULL, blank=True, null=True, verbose_name='related country')
    iso_code = models.CharField(max_length=10)
    short_code = models.CharField(max_length=10, null=True, blank=True)
    status = models.BooleanField(default=True)

    def __str__(self):
        return self.name

class PortDetail(models.Model):
    port = models.OneToOneField(PortList, models.CASCADE, verbose_name='related port', primary_key=True)
    phone = models.CharField(max_length=15)
    district_list_id = models.ForeignKey(DistrictList, models.SET_NULL, blank=True, null=True,
                                         verbose_name='related district')
    email = models.EmailField()
    fax = models.CharField(max_length=100, null=True, blank=True)
    address = models.TextField()
    map_location = models.CharField(max_length=45, null=True, blank=True)
    other_information = models.TextField(null=True, blank=True)
    current_pricing = models.IntegerField(null=True, blank=True)

    def __str__(self):
        return self.port.name+' Details'

serializers.py

from rest_framework import serializers
from port_manager.models import PortList, PortDetail
from location.models import CountryList, DistrictList

class PortListSerializer(serializers.ModelSerializer):
    countryList_id = serializers.PrimaryKeyRelatedField(queryset=CountryList.objects.all(), write_only=True)
    class Meta:
        model = PortList
        fields = ('name', 'countryList_id', 'iso_code')

class PortDetailSerializer(serializers.ModelSerializer):
    district_list_id = serializers.PrimaryKeyRelatedField(queryset=DistrictList.objects.all(),)
    class Meta:
        model = PortDetail
        fields = ('port', 'phone', 'district_list_id', 'email', 'fax', 'address',
                  'map_location', 'other_information', 'current_pricing')

class PortSerializer(serializers.ModelSerializer):
    port = PortListSerializer()
    district_list_id = serializers.PrimaryKeyRelatedField(queryset=DistrictList.objects.all(), write_only=True)
    class Meta:
        model = PortDetail

    def create(self, validated_data):
        port_data = validated_data.pop('port')
        port = PortList.objects.create(**port_data)
        PortDetail.objects.create(port=port, **validated_data)
        return PortDetail

现在当我使用 CURL POST 到终点时,它会插入到数据库中的两个表中,但会引发错误(400)

curl示例POST请求

curl -H "Authorization: Token afab77f7c9320d396442eb1aef9a3bd5de54c3ce" -X POST -d '{"port":{"name":"Singapore", "countryList_id":"3", "iso_code":"SIN", "short_code":"898"},"district_list_id":"9", "email":"asd@aassd.com", "fax":"23423432", "other_information":"adasd sdas", "address":"asdas asd", "phone":"123412312"}' http://example.org/api/v1/portcombined/

Django错误日志的完整堆栈:

Internal Server Error: /api/v1/portcombined/
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/site-packages/django/core/handlers/base.py", line 149, in get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/local/lib/python3.5/site-packages/django/core/handlers/base.py", line 147, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.5/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/usr/local/lib/python3.5/site-packages/django/views/generic/base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.5/site-packages/rest_framework/views.py", line 466, in dispatch
    response = self.handle_exception(exc)
  File "/usr/local/lib/python3.5/site-packages/rest_framework/views.py", line 463, in dispatch
    response = handler(request, *args, **kwargs)
  File "/usr/local/lib/python3.5/site-packages/rest_framework/decorators.py", line 53, in handler
    return func(*args, **kwargs)
  File "/home/gpsl/sites/container/src/port_manager/views.py", line 143, in port_merged
    return JSONResponse(serializer.data, status=201)
  File "/usr/local/lib/python3.5/site-packages/rest_framework/serializers.py", line 503, in data
    ret = super(Serializer, self).data
  File "/usr/local/lib/python3.5/site-packages/rest_framework/serializers.py", line 239, in data
    self._data = self.to_representation(self.instance)
  File "/usr/local/lib/python3.5/site-packages/rest_framework/serializers.py", line 472, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "/usr/local/lib/python3.5/site-packages/rest_framework/serializers.py", line 463, in to_representation
    attribute = field.get_attribute(instance)
  File "/usr/local/lib/python3.5/site-packages/rest_framework/relations.py", line 157, in get_attribute
    return get_attribute(instance, self.source_attrs)
  File "/usr/local/lib/python3.5/site-packages/rest_framework/fields.py", line 80, in get_attribute
    instance = getattr(instance, attr)
AttributeError: 'ForwardManyToOneDescriptor' object has no attribute 'countryList_id'

感谢大家抽出时间并完成所有这些工作。

2 个答案:

答案 0 :(得分:1)

问题是上下文没有传递给嵌套的序列化程序。您的PortSerializer类应该有一个__init__方法,您应该明确地将上下文传递给嵌套的序列化程序。请参阅以下示例:

class PortSerializer(serializers.ModelSerializer):
    def __init__(self, *args, **kwargs):
        super(PortSerializer, self).__init__(*args, **kwargs)
        self.fields['port'] = PortListSerializer(context=self.context)

答案 1 :(得分:0)

我认为,你不应该使用$results = available_dates(); modelfield。因为,默认情况下,Django返回带有countryList_id的对象的id。

如果您使用object_id重命名模型并从API传递countryList,则Django肯定会获得countryList对象。