Django使用DetailView访问导师详情页时异常切换当前登录用户求助
问题描述
项目存在学生、导师两种用户类型,使用ListView渲染导师列表,展示导师姓名、个人简介头、自我介绍,功能运行正常。给三个展示字段添加了跳转对应导师个人详情页的链接,详情页采用基于类的视图(CBV)DetailView实现,本身渲染功能正常。
存在的异常问题:以学生身份点击列表中的导师详情链接时,当前账号身份/用户类型会切换为对应被访问的导师,点击首页或网站其他任意页面后,身份会恢复正常。
佐证截图
- 导师列表页截图,右上角可看到以学生身份登录:

- 导师详情页截图,右上角可看到身份切换为名为joss的导师:

相关代码
模型(models)代码
class User(AbstractUser): is_student = models.BooleanField(default=False) is_tutor = models.BooleanField(default=False) first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100) email = models.EmailField(max_length=100) phone_number = models.CharField(max_length=11, blank=False) current_address = models.CharField(max_length=100) image = models.ImageField(default='default_pic.jpg', upload_to=path_and_rename, verbose_name='Profile Pictures') def __str__(self): return f'{self.username}' class StudentProfile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='student_profile') def __str__(self): return f"{self.user.first_name} {self.user.last_name} Profile" class TutorProfile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='tutor_profile') profile_headline = models.CharField(max_length=200, null=True) bio = models.TextField(max_length=500, blank=True, null=True) is_validated = models.BooleanField(default=False) DAYS = (('Monday', 'Monday'), ('Tuesday', 'Tuesday'), ('Wednesday', 'Wednesday'), ('Thursday', 'Thursday'), ('Friday', 'Friday'), ('Saturday', 'Saturday'), ('Sunday', 'Sunday'),) LANG = (('Javascript', 'Javascript'), ('Python', 'Python'), ('Swift', 'Swift'), ('Java', 'Java'), ('Sql', 'Sql'), ('PHP', 'PHP'), ('C#', 'C#'),) programming_languages = MultiSelectField(choices=LANG, null=True) availability = MultiSelectField(choices=DAYS, null=True) def __str__(self): return f"{self.user.first_name} {self.user.last_name} Profile"
视图(views)代码
class TutorListView(LoginRequiredMixin,ListView): model = User template_name = 'accounts/tutor_list.html' context_object_name = 'tutors' ordering = ['userrating'] paginate_by = 5 class TutorDetailView(LoginRequiredMixin,DetailView): model = User template_name = 'accounts/tutor_detail_view.html' class ProfileView(LoginRequiredMixin, TemplateView): template_name = 'accounts/profile.html'
问题原因与解决方案
问题原因
这是模板上下文变量命名冲突导致的,你的用户登录态并没有真的被修改:
Django默认会将当前登录的用户对象注入到所有模板的上下文中,变量名为user;而你使用的DetailView会自动将查询到的模型对象注入到模板上下文,变量名默认是模型名的小写形式,你的DetailView关联的是User模型,所以注入的变量名也是user,直接覆盖了默认的登录用户变量,才会导致页面右上角显示为被访问的导师身份。跳转其他页面时没有同名变量覆盖,就会恢复显示正常的登录用户身份。
解决方案
方案1(推荐):修改DetailView的上下文变量名
给TutorDetailView添加context_object_name属性,自定义导师对象的变量名,避免和登录用户的user变量冲突:
class TutorDetailView(LoginRequiredMixin,DetailView): model = User template_name = 'accounts/tutor_detail_view.html' context_object_name = 'tutor' # 新增该行
修改完成后,将导师详情页模板中所有引用导师信息的user.xxx改为tutor.xxx即可。
方案2:统一使用request.user获取登录用户
如果不想修改视图代码,也可以直接修改模板,所有显示当前登录用户信息的位置,全部改用request.user.xxx来取值,不要使用user.xxx,即可避免变量覆盖的影响。
内容的提问来源于stack exchange,提问作者JustinAlvarez
相关产品推荐
相关产品推荐

