串行工作在Django的外壳,但在视图中失败
我有那些机型:串行工作在Django的外壳,但在视图中失败
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
:即使我只需要其id
,我也必须通过完整的ServiceCategory
。上面的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
对象确实被添加到数据库 - 但是当我通过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)
那我做错了吗?
理解序列化程序中的相关字段是如何工作的常见问题。 ForeignKey
默认使用PrimaryKeyRelatedField
,所以即使您不需要重写create
方法,也不需要IntegerField
。
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
谢谢。很有价值的信息。接受和upvoted。 – Duos
@Duos您的欢迎 –