Skip to main content
 首页 » 编程设计

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

2025年04月02日31zhujiabin

我正在开发一个基于 Django 的 cargo 管理应用程序。我们已经集成了 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)