【问题标题】:Cleaner way to serialize a collection and handling a post request with multiple instances of the model使用模型的多个实例序列化集合和处理发布请求的更简洁方法
【发布时间】:2017-03-20 04:06:50
【问题描述】:

我是 DRF 的新手,我一直在尝试向服务器发出 POST 请求。我希望每个请求都发送多个联系方式,如下所示:

   {
      "firstName":"Ryan",
      "lastName":"Reynolds",
      "numbers":[
          1234567891, 9876543219
      ]
   }

...或类似的东西。

我的模型如下所示:

class Contact(models.Model):
firstName = models.CharField(max_length=50)
lastName = models.CharField(max_length=50)


class PhoneNumber(models.Model):
    contact = models.ForeignKey(Contact, related_name='numbers', on_delete=models.CASCADE)
    phoneNumber = models.CharField(max_length=10)

每个联系人可以有多个电话号码,所以我这样编写序列化程序:

class PhoneNumberSerializer(serializers.ModelSerializer):
    class Meta:
        model = PhoneNumber
        fields = ['phoneNumber']


class ContactSerializer(serializers.ModelSerializer):
    numbers = PhoneNumberSerializer(many=True)

    class Meta:
        model = Contact
        fields = ('firstName', 'lastName', 'numbers')

    def create(self, validated_data):
        numbers_data = validated_data.pop('numbers')
        contact = Contact.objects.create(**validated_data)

        for number_data in numbers_data:
            PhoneNumber.objects.create(contact=contact, **number_data)
        return contact

我的 views.py 看起来像这样:

class ContactView(APIView):

    def get(self, request, format=None):
        snippets = Contact.objects.all()
        serializer = ContactSerializer(snippets, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = ContactSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

它接受这种格式的 JSON...

   {
      "firstName":"Ryan",
      "lastName":"Reynolds",
      "numbers":[
         {
            "phoneNumber":"6969666222"
         },
         {
            "phoneNumber":"2342342312"
         }
      ]
   }

...这和我想的不太一样。

我的问题是

  1. 我可以重写序列化程序/视图,使其可以接受格式更清晰的数字吗?也许是一个数字数组,或者至少是一个包含所有数字的字典,而不是它现在的工作方式?
  2. 我想在同一个 POST 中发送多个联系人。因此,许多响应的结构类似于我在上面定义的一个数组,然后将每个响应作为单独的元素添加到数据库中。我该怎么做呢?

【问题讨论】:

    标签: python json rest django-rest-framework serialization


    【解决方案1】:

    使用以下更新的代码

    序列化器.py

    class PhoneNumberSerializer(serializers.ModelSerializer):
        class Meta:
            model = PhoneNumber
            fields = ['phoneNumber', 'contanct']
    
    
    class ContactSerializer(serializers.ModelSerializer):
        numbers = PhoneNumberSerializer(many=True, read_only=True)
    
        class Meta:
            model = Contact
            fields = ('firstName', 'lastName', 'numbers')
    
        def create(self, validated_data):
            return Contact.objects.create(**validated_data)
    

    views.py

    class ContactView(APIView):
        def get(self, request, format=None):
            snippets = Contact.objects.all()
            serializer = ContactSerializer(snippets, many=True)
            return Response(serializer.data)
    
        def post(self, request, format=None):
            serializer = ContactSerializer(data=request.data)
            if serializer.is_valid():
                contact = serializer.save()
                numbers = request.data.get('numbers', '').split(',')
                new_data = []
                for number in numbers:
                    temp = {}
                    temp['phoneNumber'] = number
                    temp['contact'] = contact.id
                    new_data.append(temp)
                serializer = PhoneNumberSerializer(data=request.data, many=True)
                if serializer.is_valid():
                    serializer.save()
                serializer = ContactSerializer(contact)
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    

    它运行顺利,但您仍需要在您的项目中尝试此解决方案,并让我知道它是否有效。

    通过以下方式传递数据:

    {
        "firstName":"Ryan",
        "lastName":"Reynolds",
        "numbers": "1234567891,9876543219"
    }
    

    【讨论】:

    • 感谢您的帮助。它似乎仍然期待一些奇怪的东西——它想要一个用于“数字”字段的字典数组——这与我之前遇到的问题很相似。
    • 如果您仍然遇到任何错误,请在此处粘贴错误以及更新的序列化程序、视图和请求数据示例。
    • @Zalarox 如果您发现此解决方案有用,请接受此答案。
    猜你喜欢
    • 1970-01-01
    • 2016-08-21
    • 2020-04-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    相关资源
    最近更新 更多