首页 > 解决方案 > 由于 IntegrityError 类型的 TypeError 对象不是 JSON 可序列化的,因此无法使用 DRF 将数据插入模型

问题描述

我有一个表单数据,我想将其插入两个不同的模型中。所以起初我创建了两个模型,如下所示 -

这是模型User

class User(AbstractBaseUser, PermissionsMixin):

    first_name = models.CharField(max_length=255, blank=False)
    last_name = models.CharField(max_length=255, blank=False)
    email = models.EmailField(max_length=255, blank=False, unique= True)
    phone_number = models.BigIntegerField(blank=False, unique= True)
    password = models.TextField(blank=False)
    company_name = models.CharField(max_length=255, blank=True)
    is_active = models.BooleanField(default= True)
    role = models.ForeignKey(Role, on_delete=models.CASCADE, blank=False)
    business = models.ForeignKey(Businesses, on_delete=models.CASCADE, blank=True)

    objects = UserManager()

    USERNAME_FIELD = 'email'

    def __str__(self):

        return 'User Object ({})'.format(self.id)

这是模型DeliveryAgent

class DeliveryAgentVehicle(models.Model):
    vehicle_model = models.CharField(max_length=255, blank=False)
    year_of_make = models.IntegerField(blank=False)
    vehicle_photo = models.ImageField(upload_to='vehicle_photo/', max_length=None, null=True, blank=False)
    driver_license = models.ImageField(upload_to='driver_license/', max_length=None, blank=False)
    user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)

    def __str__(self):

        return 'DeliveryAgentVehicle Object ({})'.format(self.id)

这是我的表单数据

然后我创建了名为DeliveryAPIView()的APIView

在这个视图中,我首先声明了 parser_classes。然后在 post 方法中,我通过添加 key 作为角色和id(角色Delivery_agent)作为值来更新 request.data 字典。我这样做是为了让这个视图只会创建类型的用户Delivery_Agent

class DeliveryAPIView(APIView):

    parser_classes = (FormParser, MultiPartParser)

    def post(self, request, format=None):

        request.data['role'] = Role.objects.get(role_name='Delivery_agent').id

        deserialized_data = DeliverySerializer(data=request.data)

        if deserialized_data.is_valid():
            try:
                delivery_agent = deserialized_data.save()
            except IntegrityError as identifier:
                return Response(identifier)
        return Response({
            "message":"Done"
        })

由于我想将表单数据存储到两个不同的模型中,因此我将validate_data字典拆分为两个单独的字典delivey_agent_vehicledelivery_agent序列化程序。

要将车辆详细信息与送货代理映射,我首先需要拥有user_id送货代理。因此,要创建交付代理,我必须将字典传递delivey_agentcreate_user()属于User模型经理的方法。然后期望它将创建交付代理并返回交付代理的字符串表示实例,我调用create()了方法DeliveryAgentVehicle来插入交付代理的车辆详细信息。

这就是我的序列化程序的样子 -

class DeliverySerializer(serializers.Serializer):
    email = serializers.EmailField(max_length=255, required=True)
    password = serializers.CharField(max_length=255, required=True)
    first_name = serializers.CharField(max_length=255, required=True)
    last_name = serializers.CharField(max_length=255, required=True)
    phone_number = serializers.IntegerField(required=True)
    role = serializers.IntegerField(required=True)
    vehicle_model = serializers.CharField(max_length=255, required=True)
    year_of_make = serializers.CharField(max_length=255, required=True)
    photo_of_vehicle = serializers.ImageField(max_length=None, allow_empty_file=False)
    driver_license = serializers.ImageField(max_length=None, allow_empty_file=False)

    def create(self, validated_data):

        validated_data['role'] = Role.objects.get(pk=validated_data['role'])

        delivey_agent={}

        delivey_agent['email'] = validated_data['email']
        delivey_agent['password'] = validated_data['password']
        delivey_agent['first_name'] = validated_data['first_name']
        delivey_agent['last_name'] = validated_data['last_name']
        delivey_agent['phone_number'] = validated_data['phone_number']
        delivey_agent['role'] = validated_data['role']

        agent_id = User.objects.create_user(**delivey_agent)

        delivey_agent_vehicle={}

        delivey_agent_vehicle['vehicle_model'] = validated_data['vehicle_model']
        delivey_agent_vehicle['vehicle_model'] = validated_data['year_of_make']
        delivey_agent_vehicle['vehicle_model'] = validated_data[ 'photo_of_vehicle']
        delivey_agent_vehicle['vehicle_model'] = validated_data['driver_license']
        delivey_agent_vehicle['user'] = agent_id

        agent_vehicle_id = DeliveryAgentVehicle.objects.create(**delivey_agent_vehicle)

        print(delivey_agent_vehicle)
        print(delivey_agent)

        return agent_id

这是它返回的错误 -

Internal Server Error: /users/delivery/signup/
Traceback (most recent call last):
  File "/Users/jeetpatel/Desktop/env/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/Users/jeetpatel/Desktop/env/lib/python3.7/site-packages/django/core/handlers/base.py", line 145, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/jeetpatel/Desktop/env/lib/python3.7/site-packages/django/core/handlers/base.py", line 143, in _get_response
    response = response.render()
  File "/Users/jeetpatel/Desktop/env/lib/python3.7/site-packages/django/template/response.py", line 105, in render
    self.content = self.rendered_content
  File "/Users/jeetpatel/Desktop/env/lib/python3.7/site-packages/rest_framework/response.py", line 70, in rendered_content
    ret = renderer.render(self.data, accepted_media_type, context)
  File "/Users/jeetpatel/Desktop/env/lib/python3.7/site-packages/rest_framework/renderers.py", line 103, in render
    allow_nan=not self.strict, separators=separators
  File "/Users/jeetpatel/Desktop/env/lib/python3.7/site-packages/rest_framework/utils/json.py", line 25, in dumps
    return json.dumps(*args, **kwargs)
  File "/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/Users/jeetpatel/Desktop/env/lib/python3.7/site-packages/rest_framework/utils/encoders.py", line 67, in default
    return super().default(obj)
  File "/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type IntegrityError is not JSON serializable

标签: pythondjango-rest-framework

解决方案


你的错误在这里:

        try:
            delivery_agent = deserialized_data.save()
        except IntegrityError as identifier:
            return Response(identifier)

响应期望一个 JSON 可序列化对象返回给用户,该对象通常是序列化器数据,一个字典。但是,您将IntegrityError捕获的对象传递给它。

如果您想将原始数据库错误消息返回给客户端(这是不可取的),您应该执行以下操作:

try:
    delivery_agent = deserialized_data.save()
except IntegrityError as identifier:
    return Response({
        "message":str(identifier)
    }, status=400)

推荐阅读