在Django REST框架中,创建扁平的读写串行器表示涉及什么?文档引用了“平面表示”(http://django-rest-framework.org/api-guide/serializers.html#dealing-with-nested-objects部分的末尾),但除了建议使用RelatedField
子类之外,不提供示例或任何内容。
例如,如何在下方提供User
和UserProfile
关系的平面表示?
# Model
class UserProfile(models.Model):
user = models.OneToOneField(User)
favourite_number = models.IntegerField()
# Serializer
class UserProfileSerializer(serializers.ModelSerializer):
email = serialisers.EmailField(source='user.email')
class Meta:
model = UserProfile
fields = ['id', 'favourite_number', 'email',]
以上UserProfileSerializer
不允许写入email
字段,但我希望它能充分表达意图。那么,如何构造一个“扁平”读写串行器来允许email
上的可写UserProfileSerializer
属性?是否可以在继承ModelSerializer时执行此操作?
感谢。
答案 0 :(得分:6)
在查看Django REST框架(DRF)源代码时,我认为DRF序列化程序与附带的模型紧密相关,以便进行反序列化。 Field
的{{1}} param使序列化目的更少。
考虑到这一点,并查看序列化程序作为封装验证和保存行为(除了它们的(非)序列化行为)我使用了两个序列化程序:每个用户和UserProfile模型一个:
source
class UserSerializer(serializer.ModelSerializer):
class Meta:
model = User
fields = ['email',]
class UserProfileSerializer(serializer.ModelSerializer):
email = serializers.EmailField(source='user.email')
class Meta:
model = UserProfile
fields = ['id', 'favourite_number', 'email',]
上的source
参数足以处理序列化情况(例如,在为GET请求提供服务时)。对于反序列化(例如,当处理PUT请求时),有必要在视图中做一些工作,结合两个序列化器的验证和保存行为:
EmailField
答案 1 :(得分:2)
首先:更好地处理嵌套写入。
第二:Serializer Relations docs对PrimaryKeyRelatedField
和SlugRelatedField
说“默认情况下此字段为读写...” - 所以如果您的电子邮件字段是唯一的(是?)它可能是你可以使用SlugRelatedField
它只会工作 - 我还没有尝试过(但是)。
第三:相反,我使用了一个普通的Field
子类,它使用source="*"
technique来接受整个对象。从那里我手动拉取to_native
中的相关字段并返回 - 这是只读的。为了写我在post_save
检查了request.DATA并在那里更新了相关对象 - 这不是自动的,但它可以工作。
所以,第四:看看你已经得到了什么,我的方法(上面)相当于将你的email
字段标记为只读,然后实施post_save
来检查{{1} }}并相应地执行更新。
答案 2 :(得分:0)
虽然这并没有严格回答这个问题 - 我认为它会解决你的需求。问题可能在于分解两个模型来表示一个实体而不是DRF问题。
从Django 1.5开始,你可以创建一个自定义用户,如果你想要的只是一些方法和额外的字段,但除了你对Django用户感到满意之外,你需要做的就是:
class MyUser(AbstractBaseUser):
favourite_number = models.IntegerField()
并在设置中:AUTH_USER_MODEL = 'myapp.myuser'
(当然还有db-migration,通过使用db_table
选项指向现有用户表并在那里添加新列,可以非常简单。
在那之后,你有DRF擅长的常见案例。