Thi*_*rry 15 python django rest django-rest-framework
到目前为止,我对Django Rest Framework非常满意,这就是为什么我几乎无法相信代码库中存在如此大的遗漏.希望有人知道如何支持这个:
class PinSerializer(serializers.ModelSerializer):
item = ItemSerializer(read_only=True, source='item')
item = serializers.IntegerSerializer(write_only=True)
class Meta:
model = Pin
Run Code Online (Sandbox Code Playgroud)
有目标
The goal here is to read:
{pin: item: {name: 'a', url: 'b'}}
but to write using an id
{pin: item: 10}
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用两个序列化程序,但这看起来像一个非常难看的解决方案: django rest框架模型序列化程序 - 读取嵌套,写入平面
Jon*_*rds 15
假设您使用OneToOneField或ForeignKey将Pin与您的Item相关联,Django将关系存储为item,但通常将Item抽象为item_id.您可以利用这一点来解决Python对象不能具有两个具有相同名称的属性(您在代码中遇到的问题)的事实.
只需添加PrimaryKeyRelatedFieldwrite属性的名称,任何写入都将设置基础关系,而任何读取都将使用抽象对象.您的最终代码将是:
class PinSerializer(serializers.ModelSerializer):
item = ItemSerializer(read_only=True)
item_id = serializers.PrimaryKeyRelatedField(write_only=True,
source='item',
queryset=Item.objects.all())
class Meta:
model = Pin
fields = ('id', 'item', 'item_id',)
Run Code Online (Sandbox Code Playgroud)
注1:我也删除source为是多余的,改"item_id": <id>到"item": <instance>,因为我认为这一定是一个错字.
注2:我实际上发现Django Rest的设置非常不直观,没有指定Item序列化器的Pin序列化器返回item_id,validate而不是validate,但这不是重点.
jef*_*fjv 11
如果您使用的是DRF 3.0,则可以实现新to_internal_value方法来覆盖item字段,将其更改为PrimaryKeyRelatedField以允许平面写入.该to_internal_value输入需要未经验证的输入数据,并应该返回将提供作为验证数据serializer.validated_data.参见文档:http://www.django-rest-framework.org/api-guide/serializers/#to_internal_valueself-data
所以在你的情况下它将是:
class ItemSerializer(ModelSerializer):
class Meta:
model = Item
class PinSerializer(ModelSerializer):
item = ItemSerializer()
# override the nested item field to PrimareKeyRelatedField on writes
def to_internal_value(self, data):
self.fields['item'] = serializers.PrimaryKeyRelatedField(queryset=Item.objects.all())
return super(PinSerializer, self).to_internal_value(data)
class Meta:
model = Pin
Run Code Online (Sandbox Code Playgroud)
有两点需要注意:可浏览的web api仍然会认为写入是嵌套的.我不知道如何解决这个问题,但我只使用Web界面进行调试,这不是什么大问题.此外,在您编写返回的项目后,将使用平面项而不是嵌套项.要解决此问题,您可以添加此代码以强制读取始终使用Item序列化程序.
def to_representation(self, obj):
self.fields['item'] = ItemSerializer()
return super(PinSerializer, self).to_representation(obj)
Run Code Online (Sandbox Code Playgroud)
我从Anton Dmitrievsky的答案中得到了这个想法:DRF:使用嵌套序列化器进行简单的外键分配?
您可以创建自定义序列化器字段(http://www.django-rest-framework.org/api-guide/fields)
该示例取自链接:
class ColourField(serializers.WritableField):
"""
Color objects are serialized into "rgb(#, #, #)" notation.
"""
def to_native(self, obj):
return "rgb(%d, %d, %d)" % (obj.red, obj.green, obj.blue)
def from_native(self, data):
data = data.strip('rgb(').rstrip(')')
red, green, blue = [int(col) for col in data.split(',')]
return Color(red, green, blue)
Run Code Online (Sandbox Code Playgroud)
然后在序列化器类中使用该字段。
| 归档时间: |
|
| 查看次数: |
3566 次 |
| 最近记录: |