You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 02:20:24