【问题标题】:Django Rest Framework - how to combine my two serializers?Django Rest Framework - 如何组合我的两个序列化程序?
【发布时间】:2016-03-09 18:16:13
【问题描述】:

我有两个模型,其中一个包含文本,另一个包含图像,并通过 ForeignKey 连接。问题围绕着我的FortuneSerializer 中的pictures 属性。为了create,我必须取消注释并注释掉另一个。而且,为了正确显示结果,我必须这样做(取消注释/注释掉)。我可以在FortuneSerializer 中成功使用修改后的create 方法,但是显示pictures 结果是个问题。

当我在FortuneSerializer 中使用PictureSerializer 时,结果正确显示如下:

    {
        "id": 16,
        "content": "win the lottery",
        "pictures": [
            {
                "id": 2,
                "image": "/media/2016/03/09/mypicture.png"
            }
        ]
    },

但是当它们正确显示时,我无法使用create 来捕捉图片。因此,我在FortuneSerializer 中注释掉PictureSerializer 并取消注释serializer.ImageField(),这将成功创建一个Fortune 实例并捕获图片,但结果不会像这样显示图片网址:

    {
        "id": 16,
        "content": "win the lottery",
        "pictures": null
    },

序列化器:

class PictureSerializer(serializers.ModelSerializer):

    class Meta:
        model = Picture
        fields = ('id', 'image')

class FortuneSerializer(serializers.ModelSerializer):

    # If uncommented, will display picture url in results, but can't create
    pictures = PictureSerializer(many=True)

    # If uncommented, will create Fortune with attached Picture,
    # but will display `null` in results
    pictures = serializers.ImageField(max_length=None, allow_empty_file=False)

    class Meta:
        model = Fortune
        fields = ('id', 'content', 'pictures')

    def create(self, validated_data):
        pictures = validated_data.pop('pictures')
        fortune = Fortune.objects.create(user=self.context['request'].user, **validated_data)
        if pictures:
            p=Picture(fortune=fortune)
            p.image.save(str(pictures), pictures)
        return fortune

型号:

class Fortune(models.Model):
    user = models.ForeignKey(User, related_name='fortunes')
    content = models.CharField(max_length=50)

class Picture(models.Model):
    fortune = models.ForeignKey(Fortune, related_name='pictures')
    image = models.ImageField(upload_to='%Y/%m/%d')

观看次数:

class FortuneList(generics.ListCreateAPIView):
    queryset = Fortune.objects.all()
    serializer_class = FortuneSerializer

def list(self, request, user_id):
    queryset = Fortune.objects.filter(user__id=user_id)
    serializer = FortuneSerializer(queryset, many=True)
    return Response(serializer.data)

有什么解决办法吗?

==== 更新 1 =====

我按照 @YPCrumble 的建议更新了 FortuneSerializerPictureSerializer

class FortuneSerializer(serializers.ModelSerializer):

    class Meta:
        model = Fortune
        fields = ('id', 'content', 'pictures')

    def create(self, validated_data):
        pictures = validated_data.pop('pictures')
        fortune = Fortune.objects.create(user=self.context['request'].user, **validated_data)

        if pictures:            
            [Picture(fortune=fortune, image=picture) for picture in pictures]

        return fortune

class PictureSerializer(serializers.ModelSerializer):

    class Meta:
        list_serializer_class = FortuneSerializer

我可以使用 DRF 默认 HTML 发布表单创建一个新的 fortune。该表单包含标题的文本输入和用于选择现有图片文件的多选菜单(使用以前的序列化程序创建,具有多文件选择输入)。我可以选择单个或多个文件并毫无问题地创建fortune,现在与新fortune 关联的图片文件将被列出。但是,我想用fortune 发布新图像。表格中没有文件输入供我选择要上传的新图片。任何指针?

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    当您为序列化程序传递many=True 标志时,您还必须传递create multiple objects in the serializer's create method

    可以根据您的 save 函数的实际外观来调整以下内容:

    def create(self, validated_data):
        pictures = validated_data.pop('pictures')
        fortune = Fortune.objects.create(user=self.context['request'].user, **validated_data)
        if pictures:            
            [Picture(fortune=fortune, image=picture) for picture in pictures]
    
        return fortune
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-08
      • 2016-12-18
      • 2017-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-04
      相关资源
      最近更新 更多