我有两个模型,其中一个包含文本,另一个包含图像,并通过外键连接。问题围绕着我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的建议更新了FortuneSerializer
和PictureSerializer
:
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