There are two models: Product and Picture. Each Product can have several Pictures. I have questions when I want to create a Product using POST. How to POST a nested object containing a ImageField list?
The Product model is:
class Product(models.Model):
    product_id = models.AutoField(primary_key=True)
    product_name = models.CharField(max_length=50)
    description = models.TextField(blank=True)
The Picture model is:
class Picture(models.Model):
    product = models.ForeignKey(Product, related_name='pictures')
    path = models.ImageField(null=False, upload_to='product_pic')
    description = models.CharField(max_length=255, null=True, blank=True)
    main = models.BooleanField()
I write the serializer.py as follow:
class PictureSerializer(serializers.ModelSerializer):
    class Meta:
        model = Picture
        fields = ('path', 'description', 'main')
class ProductSerializer(serializers.ModelSerializer): 
    pictures = PictureSerializer(many=True, required=False)
    class Meta:
        model = Product
        fields = ('product_id', 'product_name', 'pictures', 'description')
The view that I am using is:
class ProductEnum(generics.ListCreateAPIView):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    permission_classes = (IsAuthenticated, )
    def post(self, request, format=None):
        serializer = ProductSerializer(data=request.DATA, files=request.FILES)
        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)
I am registering it in the urls as:
url(r'^api/products/$', views.ProductEnum.as_view()),
The questions are:
django-rest-framework tells me that "Lists are not currently supported in HTML input"Product resources with multiple Pictures. OR I must use multipart parser.You have to use multipart parser, as soon as you need to send binary data you basically only have to choices:
An approach that can be seen quite often is to create an (non rest) view to upload single/multiple files which create File or Document objects (returning an id on upload). Then you can use these id(s) which another request, in your case creating/updating your Product.
In general there is no easy way to do that because json doesn't support binary data.
DRF makes this quite easy to do. You are close, you need to override ProductSerializer.create, something like this:
class ProductSerializer(serializers.ModelSerializer): 
    pictures = PictureSerializer(many=True, required=False)
    class Meta:
        model = Product
        fields = ('product_id', 'product_name', 'pictures', 'description')
    def create(self, validated_data):
        # Pop this from the validated_data first, since the serializer can't handle it.
        pictures = validated_data.pop('pictures')
        product = super().create(validated_data)
        # Now that we have a product to reference in the FKey, create the pictures.
        for picture in pictures:
            # `picture` has been run through the PictureSerialzer, so it's valid. 
            picture['product'] = product
            Picture.objects.create(**picture)
        return product
There's a full example in the docs, here: http://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers
For your curl command, it's going to be something like:
curl -X POST http://localhost:8000/products/ -H 'ContentType: application/json' -d '{"pictures": [{"description": "first one"}, {"description": "second one"}], "product_name": "foobar"}'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With