serializer 中的read_only 和 write_only介绍
在 Django REST Framework (DRF) 中,read_only 和 write_only 是 Serializer 字段的重要参数,用于控制字段在序列化(输出)和反序列化(输入)时的行为。以下是详细介绍:
1. read_only=True
#作用:
- 序列化时包含该字段(API 返回数据中会显示)
- 反序列化时忽略该字段(用户无法通过请求修改该字段)
- 通常用于自动生成或计算的字段(如 ID、创建时间、计算值等)
#示例:
class UserSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=True) # 用户无法修改ID
created_at = serializers.DateTimeField(read_only=True) # 自动生成的创建时间
class Meta:
model = User
fields = ['id', 'username', 'email', 'created_at']
#效果:
请求数据(反序列化):
{
"username": "test",
"email": "test@example.com",
"id": 123, // 该字段会被忽略
"created_at": "2025-06-25T10:00:00Z" // 该字段会被忽略
}
响应数据(序列化):
{
"id": 1,
"username": "test",
"email": "test@example.com",
"created_at": "2025-06-25T10:00:00Z"
}
2. write_only=True
#作用:
序列化时忽略该字段(API 返回数据中不显示)
反序列化时包含该字段(用户可以通过请求传递该字段)
通常用于敏感信息(如密码、令牌等)或只需写入不需要返回的字段
#示例:
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True) # 密码不应返回给客户端
class Meta:
model = User
fields = ['username', 'email', 'password']
def create(self, validated_data):
# 手动处理密码哈希
password = validated_data.pop('password')
user = User.objects.create(**validated_data)
user.set_password(password) # 哈希密码
user.save()
return user
#效果:
请求数据(反序列化):
{
"username": "test",
"email": "test@example.com",
"password": "securepassword" // 该字段会被处理
}
响应数据(序列化):
{
"username": "test",
"email": "test@example.com"
// 密码字段不会返回
}
3. 同时使用 read_only 和 write_only
#示例:
假设需要一个字段在创建时由用户提供(write_only),但创建后只能读取(read_only)。可以通过两个字段实现:
class OrderSerializer(serializers.ModelSerializer):
# 创建时用户提供优惠券代码
coupon_code = serializers.CharField(write_only=True, required=False)
# 创建后返回优惠券折扣金额
discount_amount = serializers.DecimalField(
max_digits=10,
decimal_places=2,
read_only=True
)
class Meta:
model = Order
fields = ['coupon_code', 'discount_amount', 'total_price']
def create(self, validated_data):
coupon_code = validated_data.pop('coupon_code', None)
# 计算折扣逻辑...
discount = calculate_discount(coupon_code)
order = Order.objects.create(
discount_amount=discount,
**validated_data
)
return order
4. 在 extra_kwargs 中设置
#在 Meta 类的 extra_kwargs 中设置更简洁:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'email', 'password', 'created_at']
extra_kwargs = {
'id': {'read_only': True},
'password': {'write_only': True, 'min_length': 8},
'created_at': {'read_only': True}
}
5. 常见应用场景
#read_only 的场景
自动生成的字段:id、created_at、updated_at
计算字段:total_price = price * quantity
关联字段:如 user.profile.avatar_url
#write_only 的场景
密码、API 密钥等敏感信息
一次性使用的字段:如验证码、临时令牌
创建 / 更新时需要但无需返回的字段:如 old_password(修改密码时)
6. 注意事项
#验证逻辑:
read_only 字段不会参与反序列化验证
write_only 字段不会参与序列化输出
#默认值:
如果设置 read_only=True,则无需指定 default 值,因为该字段不会被写入
#与 required 的关系:
read_only=True 隐含 required=False
write_only=True 仍可设置 required=True(如果该字段在创建 / 更新时必须提供)
通过合理使用 read_only 和 write_only,可以精确控制 API 的输入输出字段,提高安全性和用户体验。
在你说话之前,先听;在你回应之前,先想;在你消费之前,先挣;在你退出之前,先试