There are two models: Product
and Picture
. Each Product
can have several Picture
s. 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