Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Django multipart/form-data pass Dict & File

I want to create a post requests that sends a file along with information in the form of a dictionary. I have the following implementation:

# conftest.py
import pytest


@pytest.fixture
def api_client():
    from rest_framework.test import APIClient

    return APIClient()

Testing with 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

Server side:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

# 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)

Lastly, the Dataset model is:

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)

The response i am getting is a combination of the dict and the file data. How can i handle the data and the file in the server side (views.py)?

>Solution :

Django can handle such requests via form. So the pattern is the following:

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)

    

Note that you will need to have a field that can store file on your model. E.g: file = models.FileField(upload_to='attachments', blank=False)

Then content of fields in dictionary (and content of your file) will be automatically mapped via form to the relevant fields.

See additional info: https://docs.djangoproject.com/en/4.0/topics/forms/

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading