如何实现Django表单Author字段自动预填充当前登录用户?
解决评论表单自动填充当前登录用户的问题
核心问题分析
你当前的代码存在几个关键错误:
- POST请求时
initial参数会被POST数据覆盖,无法生效 - 错误调用
get_initial(self),这里的self并非表单实例,逻辑完全错误 - 表单保留
author字段存在安全风险(前端可篡改),且没有正确传递初始值
分步解决方案
1. 修改表单(两种可选方案)
方案一:完全移除author字段(推荐,最安全)
因为author是当前登录用户,不需要用户输入,直接从表单中移除,避免前端篡改:
class ReviewForm(forms.ModelForm): class Meta: model = Review # 去掉author字段,仅保留需要用户填写的内容 fields = ('stars', 'comment',)
方案二:保留只读的author显示(如果需要在页面展示作者)
如果要在页面显示当前用户名且不允许修改,添加只读字段:
class ReviewForm(forms.ModelForm): # 添加只读的作者字段,无需用户填写 author = forms.CharField(disabled=True, required=False) class Meta: model = Review fields = ('author', 'stars', 'comment',)
2. 修正视图函数
from django.contrib.auth.decorators import login_required # 强制要求用户登录才能提交评论 @login_required def review(request, media_type, media_id): # 获取对应媒体对象 try: if media_type == 'movie': media = Movie.objects.get(id=media_id) elif media_type == 'game': media = Game.objects.get(id=media_id) elif media_type == 'show': media = Show.objects.get(id=media_id) else: raise Http404 except (Movie.DoesNotExist, Game.DoesNotExist, Show.DoesNotExist): raise Http404 if request.method == 'POST': form = ReviewForm(request.POST) if form.is_valid(): review = form.save(commit=False) # 直接给评论实例赋值当前登录用户 review.author = request.user review.media_type = media_type review.media_id = media_id # 简化媒体关联逻辑,替代多个if-elif setattr(review, media_type, media) review.save() # 评论保存后重定向到媒体详情页,避免重复提交 # return redirect('media_detail', media_type=media_type, media_id=media_id) else: # GET请求时传递初始作者值(仅针对方案二) form = ReviewForm(initial={'author': request.user.username}) context = { 'form': form, 'media': media } return render(request, 'review.html', context)
关键修正点说明
- 用
@login_required确保只有登录用户能访问评论页面,避免request.user为匿名用户 - POST请求时直接通过
review.author = request.user赋值,完全绕开表单,安全可靠 - 用
setattr简化媒体对象关联代码,减少冗余的if-elif判断 - 处理媒体对象时添加异常捕获,避免ID不存在时抛出错误
内容的提问来源于stack exchange,提问作者ShinglesGordon98
相关产品推荐
相关产品推荐

