Django Rest Framework - 如何组合我的两个序列化程序



我有两个模型,其中一个包含文本,另一个包含图像,并通过外键连接。问题围绕着我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()这将成功创建财富实例并捕获图片,但结果不会像这样显示图片 url:

    {
        "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的新图像。表单中没有文件输入供我选择要上传的新图片。有什么指示吗?

传递序列化程序的 many=True 标志时,还必须在序列化程序的 create 方法中创建多个对象。

可以根据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

相关内容

最新更新