I have two models one of which contains text and the other an image and are connected via a ForeignKey. The problem revolves around the pictures attribute in my FortuneSerializer. In order to create I have to uncomment one and comment out another. And, in order to display the results correctly I have to do the same (uncomment/comment out). I can successfully use the modified create method in the FortuneSerializer but displaying the pictures results is a problem.
When I use the PictureSerializer inside of the FortuneSerializer results are displayed correctly like so:
{
"id": 16,
"content": "win the lottery",
"pictures": [
{
"id": 2,
"image": "/media/2016/03/09/mypicture.png"
}
]
},
but while they display properly I can't use the create to capture the picture. Because of this I comment out PictureSerializer in the FortuneSerializer and uncomment serializer.ImageField() which will successfully create a Fortune instance and capture the picture, but the results don't display the picture url like so:
{
"id": 16,
"content": "win the lottery",
"pictures": null
},
Serializers:
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
Models:
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')
Views:
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)
Any solutions?
==== UPDATE 1 =====
I updated the FortuneSerializer and PictureSerializer as @YPCrumble suggested:
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
I can create a new fortune using the DRF default HTML post form. The form contains a text input for the title and a multiple select menu to select existing picture files (created using the previous serializers, which has a multi file select input). I can select single or multiple files and create the fortune with no problems and the picture files now associated with the new fortune will be listed. However, I'd like to POST new images with fortune. There is no file input in the form for me to select new pictures to upload. Any pointers?