【问题标题】:Django REST Framework ManyToMany ErrorDjango REST框架多对多错误
【发布时间】:2018-10-15 23:45:27
【问题描述】:

当我为 ManyToMany 字段添加序列化程序时,它会在 REST API 上显示结果,但是当我发布数据时,序列化程序会将 is_valid() 设为 false。 当我将它们称为 JSONFields 时,序列化程序 is_valid() 为 True 并且数据被保存,但在 localhost 上查看 api 时出现以下错误 - 'ManyRelatedManager' 类型的对象不是 JSON 可序列化的'

class B(models.model):
    name = models.CharField()

class A(models.model):
    b = models.ManyToManyField(B)

class BSerializer(serializer.modelSerializer):
    class Meta:
        model=B
        fields = '__all__'

class ASerializer(serializer.ModelSerializer):
    b = BSerializer(many=true)

    def save(self):
        b_data = self.validated_data.pop('b')
        a = A.objects.create(**validated_data)
        b_instance = B.objects.get(name=b_data['name'])
        a.add(b_instance)

当使用http://localhost:8000/a/REST 命中时,这在 REST 框架 UI 上提供了完美的结果,但是当我使用数据 {'b':[{'name':'foo'}]} 在邮递员上命中 POST 请求时,序列化程序失败到 is_valid() 函数。

但是当我把代码改成这样的时候:

class ASerializer(serializer.ModelSerializer):
    b = serializer.JSONField()

    def save(self):
        b_data = self.validated_data.pop('b')
        a = A.objects.create(**validated_data)
        b_instance = B.objects.get(name=b_data['name'])
        a.add(b_instance)

邮递员命中保存了 A 的数据,然后将 b 实例添加到其中。当我在 python shell 中看到数据时可以看到。但是在 REST Framework UI 上查看它时,会出现以下错误: 'ManyRelatedManager' 类型的对象不是 JSON 可序列化的'

【问题讨论】:

    标签: django python-3.x django-rest-framework django-2.0


    【解决方案1】:

    你必须创建两个单独的序列化器

    一个用于检索。

    class A_RetriveSerializer(serializer.ModelSerializer):
        b = BSerializer(many=true)
    
        class Meta:
           model = A
           fields = '__all__'
    

    和其他用于创建对象。

    class A_PostSerializer(serializer.ModelSerializer):
        b = serializer.JSONField()
    
        class Meta:
           model = A
           fields = ('b', )
    
        def save(self):
            b_data = self.validated_data.pop('b')
            a = A.objects.create(**validated_data)
            b_instance = B.objects.get(name=b_data['name'])
            a.b.add(b_instance)
    

    在您看来,覆盖 get_serializer_class 方法

    def get_serializer_class(self):
        if self.request.method == 'POST':
           return A_PostSerializer
        return A_RetriveSerializer
    

    【讨论】:

    • 上面的 get_serializer_class 可以很好地进行检索,但对于发布它会给出错误 - viewset is_valid() 中的错误缺少 1 个必需的位置参数:'self' 现在如果我将代码更改为此 def get_serializer_class( self): if self.request.method == 'POST': return CommissionRulePOSTSerializer(data=self.request.data) return CommissionRuleRetrieveSerializer(data=self.request.data) GET 请求出现此错误 - CommissionRulePOSTSerializer' 对象不可调用它适用于 POST 请求
    • 你可以发布你的视图类
    【解决方案2】:

    正如@Satendra 所回答的那样,我制作了 2 个序列化程序,但在视图集中收到错误。

    def create(self, request):
        try:
            serializer = self.get_serializer_class()
            if serializer.is_valid():
                serializer.save()
                return Response({"status": "success"})
            else:
                return Response({"status": "failure", "reason": 'Serializer not valid'})
        except Exception as e:
            print('Error in viewset', e)
            return Response({"status": "failure", "reason": e})
    

    因此,只需更改此代码,并在调用 get_serializer_class 后添加一个新行用数据实例化序列化程序,它适用于 get 和 post 请求,并为 get 和 post 使用单独的序列化程序

    serializer = serializer(data=self.request.data)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-22
      • 2019-03-16
      • 2023-03-18
      • 2018-10-14
      • 2019-03-06
      • 1970-01-01
      • 2016-04-23
      相关资源
      最近更新 更多