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