我有这些模特:
class ServiceCategory(models.Model):
class Meta:
db_table = 'service_categories'
category = models.CharField(max_length=24)
def __str__(self):
return self.category
class Service(models.Model):
class Meta:
db_table = 'services'
service = models.CharField(max_length=24)
category = models.ForeignKey('ServiceCategory')
def __str__(self):
return self.service
他们的序列化器:
class ServiceCategorySerializer(serializers.ModelSerializer):
class Meta:
model = ServiceCategory
fields = ('id', 'category')
class ServiceSerializer(serializers.ModelSerializer):
category = ServiceCategorySerializer()
class Meta:
model = Service
fields = ('id', 'service', 'category')
完成此设置后,I quickly bumped into a problem通过其关联的Service
创建新的ServiceSerializer
:我必须传递一个完整的ServiceCategory
及其所有字段,即使我只需要它的id
。上面的ServiceCategory
看起来很简单,但事实并非如此,因为为了简洁,我省略了很多其他字段。
因此,将ServiceCategory
的完整属性传递到前端的表单对我来说似乎非常低效,所以我尝试了另一种方法:
class UpsertServiceSerializer(serializers.ModelSerializer):
category = serializers.IntegerField() # not ServiceCategorySerializer()
class Meta:
model = Service
fields = ('service', 'category')
def create(self, data):
c = ServiceCategory.objects.get(pk=data['category'])
return Service.objects.create(service=data['service'], category=c)
我的目的是使用UpsertServiceSerializer
进行创建和更新,现在ServiceSerializer
用于读取。 UpsertServiceSerializer
在Django shell中没有遇到任何问题 - 创建通过我只需传递id
ServiceCategory
而不是所有属性和新Service
对象确实已添加到数据库中 - 但是当我通过Postman发出POST
请求时,我收到此错误:
TypeError at /services
int() argument must be a string, a bytes-like object or a number, not 'ServiceCategory'
所以我尝试了UpsertServiceSerializer
的新版本:
class UpsertServiceSerializer(serializers.Serializer):
service = serializers.CharField()
category = serializers.IntegerField()
def create(self, data):
c = ServiceCategory.objects.get(pk=data['category'])
return Service.objects.create(service=data['service'], category=c)
请注意,在新版本中,我对serializers.Serializer
进行了子类化,而不是serializers.ModelSerializer
,并且其中没有class Meta
。这个版本没有什么不同,它也传入Django shell,但在具有相同TypeError的视图中失败。
以下是观点:
@api_view(['GET', 'POST'])
def services(request):
if request.method == 'GET':
services = Service.objects.all()
serializer = ServiceSerializer(services, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = UpsertServiceSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
那么我做错了什么?
答案 0 :(得分:1)
了解相关字段在序列化程序中的工作方式是常见问题。 ForeignKey
默认使用PrimaryKeyRelatedField
,因此您不需要IntegerField
,即使您不需要覆盖create
方法。
class UpsertServiceSerializer(serializers.ModelSerializer):
class Meta:
model = Service
fields = ('service', 'category')
传递pk
类别只会有效。如果您需要category
模型的特殊布局而不是普通pk
,则可以编写自己的to_representation
方法。
class UpsertServiceSerializer(serializers.ModelSerializer):
...
def to_representation(self, instance):
representation = super(UpsertServiceSerializer, self).to_representation(instance)
representation['category'] = ServiceCategorySerializer(instance.category).data
return representation