themanatuf
themanatuf

Reputation: 3130

How to create an object and then set related field in Django Rest Framework

I'm trying to create a new object using Django REST Framework's ModelViewSet and the ModelSerializer and associate an existing object to it's ForeignKey field. I have two models with a one-to-many relationship, basically a manufacturer and a product. The manufacturer already exists in the database and I'm trying to add a product individually and assign it's manufacturer at the same time. When I do, DRF is giving me this error:

"non_field_errors": [ "Invalid data. Expected a dictionary, but got Product." ]

Here are what my models look like (I've tried to take out the unneeded code to keep it small). When a product is created the manufacturer field is an integer representing the ID of it's related object. As you can see in my view, I query for the Manufacturer object, set it and then continue to let DRF create the object. If someone can please tell me where I'm going wrong, I'd greatly appreciate it!

models.py

class Manufacturer(models.Model):
    name = models.CharField(max_length=64)
    state = models.CharField(max_length=2)

class Product(models.Model):
    manufacturer = models.ForeignKey(Manufacturer, related_name="products")
    name = models.CharField(max_length=64)
    sku = models.CharField(max_length=12)

views.py

class ProductViewSet(view sets.ModelViewSet):
    model = Product
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        # get logged in user's manufacturer
        return Product.objects.filter(manufacturer=manufacturer)

    def create(self, request, *args, **kwargs):
        if "manufacturer" in request.data:
            manufacturer = Manufacturer.objects.get(pk=request.data["manufacturer"])
            request.data["manufacturer"] = manufacturer

        return super(ProductViewSet, self).create(request, *args, **kwargs)

serializers.py

class ManufacturerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Manufacturer
        fields = ("id", "name", "state",)
        read_only_fields = ("id",)

class ProductSerializer(serializers.ModelSerializer):
    manufacturer = ManufacturerSerializer()

    class Meta:
        model = Product
        fields = ("id", "manufacturer", "name",)
        read_only_fields = ("id",)

Upvotes: 2

Views: 5222

Answers (1)

theguru42
theguru42

Reputation: 3378

you have to set manufacturer_id key.

change your serializer to:

class ProductSerializer(serializers.ModelSerializer):
    manufacturer = ManufacturerSerializer(read_only=True)
    manufacturer_id = serializers.IntegerField(write_only=True)

    class Meta:
        model = Product
        fields = ("id", "manufacturer", "name",)
        read_only_fields = ("id",)

change your create method to:

def create(self, request, *args, **kwargs):
    if "manufacturer" in request.data:
        request.data["manufacturer_id"] = request.data['manufacturer']

    return super(ProductViewSet, self).create(request, *args, **kwargs)

Upvotes: 3

Related Questions