我有这些模型:
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通过其关联的 ServiceSerializer
创建一个新的 Service
:我还必须传递一个完整的 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 中工作没有问题 - 创建过程中我必须只传递 ServiceCategory
的 id
而不是它的所有内容属性和新的 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 中传递,但在 View 中失败,并出现相同的 TypeError。
这是 View :
@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)
那么我做错了什么?
最佳答案
理解相关字段在序列化器中如何工作是一个常见问题。 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
关于python - 序列化器在 Django shell 中工作但在 View 中失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41352395/