如何在Django CreateView子类中访问request.user变量?
解决Django CreateView中访问request.user的问题
这个问题我之前也踩过坑!你现在的代码里直接在类的顶层属性中使用self,这是行不通的——因为类在定义阶段还没有被实例化,self只有在类的实例方法中才会存在,所以Python会抛出NameError: name 'self' is not defined这个错误。
为什么原来的写法不对?
你在类里直接写author_name = self.request.user.username,此时Python正在解析这个类的定义,还没有创建任何ViewCreate的实例,自然找不到self这个变量。initial如果写成类属性,只能是静态值,没法动态获取请求相关的信息。
正确的解决方法
有两种常用的方式可以实现自动填充作者字段的需求,推荐第二种,更高效简洁:
方法1:重写get_initial方法
CreateView提供了get_initial方法,专门用来动态生成表单的初始值,这个方法是实例方法,可以正常访问self.request:
from django.views.generic.edit import CreateView from django.contrib.auth import get_user_model import datetime class ViewCreate(CreateView): model = view_C # 记得补充你的fields或form_class,比如: # fields = ['title', 'content', 'publish_date'] def get_initial(self): # 这里可以安全访问self.request.user current_user = self.request.user publish_date = datetime.date.today() return { 'author': current_user.pk, 'publish_date': publish_date, }
方法2:重写form_valid方法(更推荐)
这种方式不需要依赖初始值,而是在表单验证通过后,直接给要保存的对象赋值,还能避免多余的数据库查询(因为self.request.user本身就是User对象,不用再通过username去查一次):
from django.views.generic.edit import CreateView from django.contrib.auth import get_user_model import datetime class ViewCreate(CreateView): model = view_C # 注意:这里不要把author包含在fields里,因为我们自动赋值 fields = ['title', 'content', 'publish_date'] def form_valid(self, form): # 直接将当前用户赋值给对象的author字段 form.instance.author = self.request.user # 设置发布日期 form.instance.publish_date = datetime.date.today() # 调用父类方法完成保存逻辑 return super().form_valid(form)
额外提示
- 如果你的表单中不需要显示
author字段,一定要确保它不在fields列表里,或者在自定义表单中将其设置为HiddenInput。 - 方法2的效率更高,因为省去了一次
get_user_model().objects.get()的数据库查询操作,而且逻辑更直接。
内容的提问来源于stack exchange,提问作者user2979885
相关产品推荐
相关产品推荐

