如何在Django Rest框架中创建对象并设置相关字段

如何在Django Rest框架中创建对象并设置相关字段,django,django-rest-framework,Django,Django Rest Framework,我正在尝试使用Django REST Framework的ModelViewSet和ModelSerializer创建一个新对象,并将现有对象与其ForeignKey字段相关联。我有两个一对多关系的模型,基本上是一个制造商和一个产品。数据库中已经存在制造商,我正在尝试单独添加一个产品,同时指定它的制造商。当我这样做时,DRF会给我以下错误: “非字段错误”:[ 无效数据。需要字典,但得到产品 ] 下面是我的模型的样子(我试图去掉不需要的代码以保持它的小)。创建产品时,制造商字段是一个整数,表示其

我正在尝试使用Django REST Framework的
ModelViewSet
ModelSerializer
创建一个新对象,并将现有对象与其
ForeignKey
字段相关联。我有两个一对多关系的模型,基本上是一个制造商和一个产品。数据库中已经存在制造商,我正在尝试单独添加一个产品,同时指定它的制造商。当我这样做时,DRF会给我以下错误:

“非字段错误”:[ 无效数据。需要字典,但得到产品 ]

下面是我的模型的样子(我试图去掉不需要的代码以保持它的小)。创建产品时,
制造商
字段是一个整数,表示其相关对象的ID。正如您在我的视图中看到的,我查询
Manufacturer
对象,设置它,然后继续让DRF创建该对象。如果有人能告诉我哪里出了问题,我将不胜感激

型号.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)
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)
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",)
视图.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)
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)
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",)
序列化程序.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)
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)
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",)

您必须设置
manufacturer\u id

将序列化程序更改为:

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",)
将创建方法更改为:

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)

这适用于插入和某种类型的更新。例如,我有一个属于制造商“a”的产品“X”。我将“X”更新为新的制造商“B”。从
update
方法返回给我的对象仍然显示“A”为制造商,但数据库实际上已更新为“B”。如果我刷新页面,它具有正确的值。我已经看过了DRF代码,似乎不明白为什么会这样。有什么想法吗?好的,我重写了序列化程序中的
update
方法,并从\u db()调用了
instance.refresh\u
,似乎解决了这个问题。这感觉有点“黑客”,但它的工作。