我不能完全确定我的问题标题是否符合我的要求,但情况确实如此:
我的HyperlinkedModelSerializer
看起来像这样:
class ParentArrivalSerializer(serializers.HyperlinkedModelSerializer):
carpool = SchoolBuildingCarpoolSerializer()
class Meta:
model = ParentArrival
正如您所看到的,carpool
被定义为嵌套的序列化器对象,我想要的是能够以这种方式发出POST请求来创建ParentArrival
(数据为application / json ):
{
...
"carpool": "http://localhost:8000/api/school-building-carpools/10/"
...
}
以这种方式接收数据:
{
"carpool": {
"url": "http://localhost:8000/api/school-building-carpools/10/"
"name": "Name of the carpool",
...
}
}
基本上,我正在寻找一种处理嵌套序列化程序的方法,而不必在POST请求中将数据作为对象(但在这种情况下为id或url)发送,但接收对象嵌套在序列化响应中
答案 0 :(得分:8)
我对之前的解决方案感到满意,但我决定重新审视,我认为我还有另一种解决方案可以完全满足您的需求。
基本上,您需要创建自己的自定义字段,并且只需覆盖to_representation
方法:
class CarpoolField(serializers.PrimaryKeyRelatedField):
def to_representation(self, value):
pk = super(CarpoolField, self).to_representation(value)
try:
item = ParentArrival.objects.get(pk=pk)
serializer = CarpoolSerializer(item)
return serializer.data
except ParentArrival.DoesNotExist:
return None
def get_choices(self, cutoff=None):
queryset = self.get_queryset()
if queryset is None:
return {}
return OrderedDict([(item.id, str(item)) for item in queryset])
class ParentArrivalSerializer(serializers.HyperlinkedModelSerializer):
carpool = CarpoolField(queryset=Carpool.objects.all())
class Meta:
model = ParentArrival
这将允许您使用
发布{
"carpool": 10
}
并获得:
{
"carpool": {
"url": "http://localhost:8000/api/school-building-carpools/10/"
"name": "Name of the carpool",
...
}
}
答案 1 :(得分:4)
很简单。
如您所知,Django appends "_id" to the field name
在ModelClass中,您可以在SerializerClass中实现,也可以实现原始文件。您要做的就是这样
class ParentArrivalSerializer(serializers.HyperlinkedModelSerializer):
# ...
carpool_id = serializers.IntegerField(write_only=True)
carpool = SchoolBuildingCarpoolSerializer(read_only=True)
# ...
class Meta:
fields = ('carpool_id', 'carpool', ...)
并在POST请求中使用carpool_id
。
答案 2 :(得分:2)
一种方法是将“拼车”保留为您从DRF获取的默认值,然后为嵌套对象添加只读字段。
这样的事情(我没有时间测试代码,所以请考虑这个伪代码。如果你不能让它工作,请告诉我,并将花更多的时间):
class ParentArrivalSerializer(serializers.HyperlinkedModelSerializer):
carpool_info = serializers.SerializerMethodField(read_only=True)
class Meta:
model = ParentArrival
fields = ('id', 'carpool', 'carpool_info',)
def get_carpool_info(self, obj):
carpool = obj.carpool
serializer = SchoolBuildingCarpoolSerializer(carpool)
return serializer.data
如果您的唯一嵌套对象是拼车,我还建议切换到常规ModelSerializer,因此拼车只显示ID(10),然后嵌套对象可以显示URL。
class ParentArrivalSerializer(serializers.ModelSerializer):
....
然后如果一切正常,你就可以用
做一个帖子{
"carpool": 10
}
和你的获得:
{
"carpool": 10
"carpool_info": {
"url": "http://localhost:8000/api/school-building-carpools/10/"
"name": "Name of the carpool",
...
}
}
我从未找到另一种解决方案,所以这是我多次使用的技巧。
答案 3 :(得分:2)
覆盖to_representation
方法怎么样?
class YourSerializer(serializers.ModelSerializer):
class Meta:
model = ModelClass
fields = ["id", "foreignkey"]
def to_representation(self, instance):
data = super(YourSerializer, self).to_representation(instance)
data['foreignkey'] = YourNestedSerializer(instance.foreignkey).data
return data