如何在DRF序列化器中将employee属性设为只读并指定对应值?
问题描述
现有如下Django REST Framework序列化器:
class MySerializer(serializers.ModelSerializer): class Meta: model = models.MyClass
对应的模型类:
class MyClass(models.Model): employee = models.ForeignKey("Employee", on_delete=models.CASCADE) work_done = models.TextField(blank=True, null=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True)
需求:
- 将
employee字段设置为只读 - 该字段仅显示当前请求用户对应的
Employee实例(即通过Employee.objects.get(user=self.request.user)获取的对象)
实现方案
方法一:序列化器内重写to_representation方法
直接在序列化器中完成字段只读设置与数据过滤:
class MySerializer(serializers.ModelSerializer): # 标记employee为只读字段 employee = serializers.PrimaryKeyRelatedField(read_only=True) class Meta: model = models.MyClass fields = ['employee', 'work_done', 'created_at', 'updated_at'] def to_representation(self, instance): representation = super().to_representation(instance) request = self.context.get('request') if request and hasattr(request, 'user'): try: current_employee = models.Employee.objects.get(user=request.user) # 仅保留当前用户对应的employee数据,不匹配则置空或移除字段 if representation['employee'] != current_employee.pk: representation['employee'] = None except models.Employee.DoesNotExist: # 处理用户未关联Employee的异常情况 representation['employee'] = None return representation
方法二:视图层配合处理(更高效)
将数据过滤逻辑放在视图层,序列化器仅负责只读展示,减少序列化阶段的开销:
序列化器代码
class MySerializer(serializers.ModelSerializer): employee = serializers.PrimaryKeyRelatedField(read_only=True) class Meta: model = models.MyClass fields = ['employee', 'work_done', 'created_at', 'updated_at']
创建视图(以CreateAPIView为例)
class MyCreateView(generics.CreateAPIView): serializer_class = MySerializer def perform_create(self, serializer): # 关联当前用户对应的Employee实例 current_employee = models.Employee.objects.get(user=self.request.user) serializer.save(employee=current_employee)
查询视图(以ListAPIView为例)
class MyListView(generics.ListAPIView): serializer_class = MySerializer def get_queryset(self): # 直接从数据库过滤出当前用户Employee关联的数据 current_employee = models.Employee.objects.get(user=self.request.user) return models.MyClass.objects.filter(employee=current_employee)
方案说明
- 方法一适合需要对每条返回数据单独做校验的场景,但需注意捕获
Employee.DoesNotExist异常,避免请求报错。 - 方法二从数据库层面直接过滤数据,性能更优,是推荐的常规做法。
内容的提问来源于stack exchange,提问作者Waleed Farrukh
相关产品推荐
相关产品推荐

