Home > OS >  How to save multipart / formdata turned into a QueryDict using Django REST Framework (DRF) and Model
How to save multipart / formdata turned into a QueryDict using Django REST Framework (DRF) and Model

Time:10-03

I am sending multipart/formdata from a Next.js API and I can format the data whichever way I want but I am struggling to get the right format.

For now, I have the following formdata:

<QueryDict: {
    'name': ['Test Product'],
    'brands[0]': ['1'],
    'brands[1]': ['2'],
    'option_types[0]': ['1'],
    'product_variants[0]option_values[0]': ['1'],
    'product_variants[0]option_values[1]': ['2'],
 >

and the following ModelSerializer:

class ProductDetailAdminSerializer(
    UniqueFieldsMixin, ProductAdminMixin, WritableNestedModelSerializer
):
    categories = PrimaryKeyRelatedField(
        many=True, allow_null=True, queryset=Category.objects.all()
    )
    option_types = PrimaryKeyRelatedField(
        many=True, allow_null=True, queryset=OptionType.objects.all()
    )
    brands = PrimaryKeyRelatedField(
        many=True, allow_null=True, queryset=Brand.objects.all()
    )
    product_variants = ProductVariantDetailAdminSerializer(many=True)

    class Meta:
        model = Product
        fields = (
            "pk",
            "name",
            "subtitle",
            "sku_symbol",
            "categories",
            "brands",
            "description",
            "option_types",
            "product_variants",
        )

My ModelSerializer is not accepting the way I am specifying the lists/arrays. For instance, if I try to do:

def validate_option_types(self, data):
    print(data)
    return data

I get an empty list meaning the format for option_types list is wrong and the same applies for the product_variants and option_values. I am simply passing the QueryDict obtained from request.data as follows:

def create(self, request, *args, **kwargs):
    serializer = ProductDetailAdminSerializer(data=request.data)
    if serializer.is_valid():
        serializer.save()
        return JsonResponse(serializer.data)
    return JsonResponse(serializer.errors, status=400)

The serializer and everything else are working fine if I use a JSON version of the QueryDict above and the JSON content-type. Incidentally, if I use ListField instead of PrimaryKeyRelatedField it also works as expected although, ListField doesn't actually give me the objects required.

So to summarise my question, what is the correct QueryDict format (specifically for fields which represent lists) for the DRF ModelSerializer? Or is there an extra step that I am missing in getting the QueryDict to the format expected by the model serializer.

CodePudding user response:

ok, You can not add many-to-many type field as the way you are trying to -

first create the object without many to many fields

obj = MyModal.save()

and then you can do something like - to create and add your many to many fields.

obj.brand.create(name='val1')
obj.option_types.create(name='val2')

You can also search StackOverflow on how to add data to ManyToManyFields

CodePudding user response:

Seems like PrimaryKeyRelatedField can't process multipart/formdata in the desired way. Here's a related question.

My solution has been to convert all the non-file form data into a single JSON string from the front-end i.e.

const formData = new FormData();
formData.append('form_data', JSON.stringify(data));

and then in Django, in the create function of my viewset, do something like

data = ujson.loads(request.data.get("form_data"))
new_query_dict = QueryDict('', mutable=True)
new_query_dict.update(data)
  • Related