create() argument after ** must be a mapping, not list, Django REST Framework (implementing my own create method error)

对着背影说爱祢 提交于 2021-01-29 16:38:08

问题


when I am implementing this code-example on the documentation (I had to implement the create method myself because I have nested objects and inserting them is not supported by default)

def create(self, validated_data):
    profile_data = validated_data.pop('profile')
    user = User.objects.create(**validated_data)
    Profile.objects.create(user=user, **profile_data)
    return user

https://www.django-rest-framework.org/api-guide/serializers/#writing-create-methods-for-nested-representations

I'm getting this error

create() argument after ** must be a mapping, not list

My implementation of the example on my project is the following :

def create(self, validated_data):
    product_data = validated_data.pop('categories')
    product = Product.objects.create(**validated_data)
    Product.objects.create(product=product, **product_data)
    return product

the whole serializers.py file

from rest_framework import serializers
from products_and_categories.models import Product, Category
from django.db import models


class CategorySerializer(serializers.ModelSerializer):
    def to_representation(self, obj):
        if 'categories' not in self.fields:
            self.fields['categories'] = CategorySerializer(obj, many=True)      
        return super(CategorySerializer, self).to_representation(obj)

    class Meta:
        model = Category
        fields = ("name", 'products', 'categories')

class ProductSerializer(serializers.ModelSerializer):
    categories = CategorySerializer(many=True)
    class Meta:
        model = Product
        fields = ("product_code", "name", "quantity", "price", 'categories')

    def create(self, validated_data):
        product_data = validated_data.pop('categories')
        product = Product.objects.create(**validated_data)
        Product.objects.create(product=product, **product_data)
        return product

my models.py file:

from django.db import models

# Create your models here.

class Category(models.Model):
    name = models.CharField(max_length=255)
    categoriesId = models.ForeignKey('self', related_name='categories',on_delete=models.CASCADE, blank=True, null=True)

class Product(models.Model):
    product_code = models.CharField(max_length=255)
    name = models.CharField(max_length=255)
    price = models.IntegerField()
    quantity = models.IntegerField()
    categories = models.ManyToManyField(Category, related_name='products')

can anybody help me figure out what's wrong ?


回答1:


You're confusing various names here. You pop the categories element from validated_data, and assign it to product_data; but it is not product data, it is a list of categories.

You then try and create a Product with that data related to an existing product - presumably you meant to create a Category there. But again what you have is a list, so you need to iterate through and create one category per entry.

And finally note that you have a many-to-many relationship between product and category, not a foreign key as in the example, so you can't use that product=product syntax.

This would be better as:

def create(self, validated_data):
    category_data = validated_data.pop('categories')
    product = Product.objects.create(**validated_data)
    for category in category_data:
        product.categories.create(**category)
    return product

(Although note that yes, creating nested items is supported by DRF; see the docs on serializer relations.)



来源:https://stackoverflow.com/questions/53418075/create-argument-after-must-be-a-mapping-not-list-django-rest-framework-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!