繁体   English   中英

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

[英]Django Rest Framework writable nested serializer raises AttributeError

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

现在名为“port_manager”的 django 应用程序具有以下模型......

模型.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'

序列化程序.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'

感谢大家花时间完成所有这些。

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

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

我认为,您不应该使用countryList_id模型字段。 因为,默认情况下,Django 使用object_id返回对象的 id。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM