Django multipart/form-data передача Dict & File
Я хочу создать пост-запрос, который отправляет файл вместе с информацией в виде словаря. У меня есть следующая реализация:
# conftest.py
import pytest
@pytest.fixture
def api_client():
from rest_framework.test import APIClient
return APIClient()
Тестирование с помощью pytest:
# test_dataset.py
@pytest.mark.django_db()
class TestDatasetEndpoint:
def test_dataset_create(self, api_client):
data_raw = baker.make(Dataset)
serialized_dataset = DatasetSerializer(data_raw).data
print(serialized_dataset)
file_path = "./Top 250s in IMDB.csv"
with open(file_path, "rb") as fp:
encoded_data = encode_multipart(
BOUNDARY, {"data": serialized_dataset, "file": fp}
)
response_post = api_client.post(
reverse("datasets-list"),
encoded_data,
content_type="multipart/form-data; boundary=BOUNDARY",
)
assert response_post.status_code == 201
Сторона сервера:
# views.py
class DatasetViewSet(viewsets.ModelViewSet):
queryset = Dataset.objects.all()
serializer_class = DatasetSerializer
def create(self, request, *args, **kwargs) -> Response:
data = request.data
return Response(request.data["data"], status=status.HTTP_201_CREATED)
Последнее, модель набора данных:
class Dataset(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=100)
path = models.CharField(max_length=100, editable=False, null=True, blank=True)
description = models.CharField(max_length=500, null=True, blank=True)
useCase = models.CharField(max_length=100, editable=False, null=True, blank=True)
useCaseSpecificVariable = models.CharField(
max_length=50, editable=False, null=True, blank=True
)
origin = models.CharField(max_length=50, editable=False, default="")
creationDate = models.DateTimeField(editable=False, null=True, blank=True)
workflowsUsedOn = models.JSONField(blank=True, null=True)
owners = models.JSONField(blank=True, null=True)
sampleSize = models.IntegerField(editable=False, default=0)
featureSize = models.IntegerField(editable=False, default=0)
metadataPath = models.CharField(
max_length=100, editable=False, null=True, blank=True
)
timeFrom = models.DateTimeField(editable=False, null=True, blank=True)
timeUntil = models.DateTimeField(editable=False, null=True, blank=True)
Ответ, который я получаю, представляет собой комбинацию данных dict и файла. Как я могу обработать данные и файл на стороне сервера (views.py)?
Django может обрабатывать такие запросы через форму. Таким образом, схема выглядит следующим образом:
forms.py
from django import forms
class DatasetForm(forms.Form):
class Meta:
model = Dataset
views.py
class DatasetViewSet(viewsets.ModelViewSet):
queryset = Dataset.objects.all()
serializer_class = DatasetSerializer
def create(self, request, *args, **kwargs) -> Response:
dataset_form = DatasetForm(request.POST, request.FILES)
if dataset_form.is_valid():
dataset = dataset_form.save()
return Response(self.serializer_class(dataset).data, status=status.HTTP_201_CREATED)
else:
return Response(dataset_form.error_messages, status=status.HTTP_400_BAD_REQUEST)
Обратите внимание, что вам нужно будет иметь поле, которое может хранить файл в вашей модели. Например: file = models.FileField(upload_to='attachments', blank=False)
Тогда содержимое полей в словаре (и содержимое вашего файла) будет автоматически отображаться через форму на соответствующие поля.
Смотрите дополнительную информацию: https://docs.djangoproject.com/en/4.0/topics/forms/