基于Django REST Framework自动设置事件作者的最优方案咨询
基于Django REST Framework的事件作者自动赋值与权限控制方案
问题背景
开发基于DRF的事件管理应用,核心需求:
- 用户发布事件时自动将自身设为作者
- 禁止通过PUT/PATCH请求修改事件作者
当前已实现重写post视图的方案,但不够精简;尝试perform_create方案时,因序列化器校验问题失败(POST请求无author字段时提示必填)。
当前实现代码
models.py
class Events(models.Model): title = models.CharField(max_length=200) description = models.CharField(max_length=200) dateday = models.DateTimeField() start_hour = models.TimeField(null=True) end_hour = models.TimeField(null=True) author = models.ForeignKey(Users, on_delete=models.CASCADE)
serializers.py
#... class EventsSerializer(serializers.ModelSerializer): class Meta: model = Events fields = '__all__' class UsersSerializer(serializers.ModelSerializer): events = EventsSerializer(many=False,read_only=True) class Meta: model = Users fields = '__all__' extra_kwargs = {'password': {'write_only': True}} #...
views.py(当前在用方案)
#... class EventsList(ListCreateAPIView): queryset = Events.objects.all() serializer_class = EventsSerializer def post(self, request): request.data['author'] = request.user.pk return super().post(request) #...
失败的perform_create尝试
class EventsList(ListCreateAPIView): queryset = Events.objects.all() serializer_class = EventsSerializer def perform_create(self, serializer): serializer.save(author=self.request.user)
问题:POST请求无
author字段时,序列化器提示该字段为必填项。
最优解决方案
1. 修复perform_create失效问题
问题根源是序列化器中author字段默认校验必填(模型中author为非空ForeignKey)。需调整序列化器,让前端无需传入author:
修改EventsSerializer:
class EventsSerializer(serializers.ModelSerializer): class Meta: model = Events fields = '__all__' extra_kwargs = { 'author': {'read_only': True} # 标记为只读,跳过前端传入校验 }
然后视图中使用perform_create自动赋值:
class EventsList(ListCreateAPIView): queryset = Events.objects.all() serializer_class = EventsSerializer def perform_create(self, serializer): serializer.save(author=self.request.user)
这样前端POST请求无需携带author字段,序列化器会忽略该字段的必填校验,由视图自动注入当前用户作为作者。
2. 禁止PUT/PATCH修改作者
方案一:序列化器层面控制
通过重写get_extra_kwargs,让author字段在非POST请求时强制只读:
class EventsSerializer(serializers.ModelSerializer): class Meta: model = Events fields = '__all__' def get_extra_kwargs(self): extra_kwargs = super().get_extra_kwargs() request = self.context.get('request') if request and request.method != 'POST': # 更新操作时,author字段只读 extra_kwargs['author'] = {'read_only': True} return extra_kwargs
方案二:视图层面强制锁定作者
针对更新视图(如RetrieveUpdateDestroyAPIView),重写perform_update方法,强制保留原作者:
class EventsDetail(RetrieveUpdateDestroyAPIView): queryset = Events.objects.all() serializer_class = EventsSerializer def perform_update(self, serializer): # 忽略前端传入的author值,保留原有作者 serializer.save(author=self.get_object().author)
3. 可复用的通用方案:自定义Mixin
若多个模型需要自动设置创建者并保护作者字段,可封装Mixin类:
class SetAuthorMixin: def perform_create(self, serializer): serializer.save(author=self.request.user) def perform_update(self, serializer): # 更新时强制锁定原作者 instance = self.get_object() serializer.save(author=instance.author)
在视图中直接继承该Mixin即可:
class EventsList(SetAuthorMixin, ListCreateAPIView): queryset = Events.objects.all() serializer_class = EventsSerializer class EventsDetail(SetAuthorMixin, RetrieveUpdateDestroyAPIView): queryset = Events.objects.all() serializer_class = EventsSerializer
内容的提问来源于stack exchange,提问作者CarlosCarraPer
相关产品推荐
相关产品推荐

