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

Django使用DetailView访问导师详情页时异常切换当前登录用户求助

问题描述

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

佐证截图
  • 导师列表页截图,右上角可看到以学生身份登录:导师列表页,右上角显示当前登录用户为学生
  • 导师详情页截图,右上角可看到身份切换为名为joss的导师:导师详情页,右上角显示身份切换为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 22:45:02