I have a DRF backend and a Angular frontend. I'm trying to create a personal library app. I want to be able to send a file and a array of objects in the same post.
requirements.txt:
asgiref==3.5.2
cffi==1.15.1
cryptography==38.0.3
Django==4.1.2
django-cors-headers==3.13.0
django-filter==22.1
django-rest-knox==4.2.0
djangorestframework==3.14.0
Markdown==3.4.1
Pillow==9.3.0
psycopg2==2.9.4
pycparser==2.21
pytz==2022.4
sqlparse==0.4.3
style==1.1.0
update==0.0.1
This is the ViewSet:
class BookViewSet(viewsets.ModelViewSet):
parser_classes = [parsers.MultiPartParser, parsers.FileUploadParser]
authentication_classes = []
queryset = Book.objects.all()
serializer_class = BookSerializer
def create(self, request, *args, **kwargs):
authors = json.loads(request.data['authors'])
date = json.loads(request.data['publishedDate'])
ISBN = json.loads(request.data['ISBN'])
date = f"{date['year']}-{date['month']}-{date['day']}"
request.data['publishedDate'] = date
request.data['authors'] = authors
request.data['ISBN'] = ISBN
print(request.data)
return super().create(request, *args, **kwargs)
This is the Serializer:
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = ['name']
class BookSerializer(serializers.ModelSerializer):
authors = AuthorSerializer(many=True)
def create(self, validated_data):
print(validated_data)
authors_data = validated_data.pop('authors')
book = Book.objects.create(**validated_data)
for author_data in authors_data:
author = Author.objects.create(**author_data)
author.books.add(book)
return book
def get_authors(self, obj):
return AuthorSerializer(
Author.objects.filter(books=obj),
many=True
).data
class Meta:
model = Book
fields = [
'thumbnail',
'title',
'subtitle',
'description',
'ISBN',
'pageCount',
'publisher',
'publishedDate',
'authors',
]
This is the print result in the ViewSet:
<QueryDict: {'title': ['"title"'], 'subtitle': ['"subtitle"'], 'description': ['"description"'], 'ISBN': ['99999999'], 'pageCount': ['123'], 'publisher': ['"publisher"'], 'publishedDate': ['2022-5-5'], 'authors': [[{"name":"author1"}, {"name":"author2"}]], 'thumbnail': [<TemporaryUploadedFile: file.jpg (image/jpeg)>]}>
It errors out in the validation because it doesn't print the validated_data and returns a response that the authors field is required.
I've tried sending a string in the authors field like this:
'authors': '[{"name":"Author"}]'
And it prints the validated_data, but without the authors field.
{'thumbnail': <TemporaryUploadedFile: file.jpg (image/jpeg)>, 'title': '"Livro"', 'subtitle': '"E seu SubtÃtulo"', 'description': '"Description"', 'ISBN': 1546789, 'pageCount': 123, 'publisher': '"Editora"', 'publishedDate': datetime.date(2022, 5, 5)}
When sending as application/json and without the file the many-to-many field works.
I couldn't get clear answers with these links: https://stackoverflow.com/questions/64500753/django-rest-framework-serialize-an-array-in-a-multipart-form-data-request https://stackoverflow.com/questions/19780731/django-rest-framework-serializer-field-required-false