如何避免Django的User DetailView覆盖当前用户{{ user }}变量?
我配置了查看特定用户信息的URL:
blog/urls.py(示例用urlpatterns +=展示片段,实际文件中并非如此)
urlpatterns += path('user/<int:pk>/', UserDetailView.as_view(), name='user-detail'),
对应的视图:
blog/views.py
class UserDetailView(DetailView): model = User template_name = 'blog/user_detail.html'
该视图继承自DetailView,使用Django的User模型。
在所有页面继承的base.html导航栏中,设置了显示当前用户昵称并链接到其个人页面:
base.html
{% if user.is_authenticated %} <a class="nav-item nav-link" href="{% url 'post-create' %}">New Post</a> <a class="nav-item nav-link" href="{% url 'user-detail' user.id %}">{{ user.username }}</a> <a class="nav-item nav-link" href="{% url 'logout-page' %}">Logout</a> {% endif %}
问题:登录后,除user/<int:pk>/页面外,导航栏用户昵称显示正常;但访问特定用户页面时,{{ user }}会从当前用户变为所查看页面的用户。
对比调用User的Post模型ListView不会影响当前用户:
blog/urls.py
urlpatterns += path('user/<str:username>', UserPostListView.as_view(), name='user-posts')
blog/views.py
class UserPostListView(ListView): model = Post template_name = 'blog/user_posts.html' context_object_name = 'posts' paginate_by = 2 def get_queryset(self): user = get_object_or_404(User, username=self.kwargs.get('username')) return Post.objects.filter(author=user).order_by('-date_posted')
请问如何避免Django的User DetailView将模板中的{{ user }}从当前用户替换为所查看的用户?
方法1:修改DetailView的context_object_name
Django的DetailView默认会把查询到的模型实例以模型类名小写的形式传入模板上下文,这里模型是User,所以默认会覆盖模板中原本代表当前登录用户的user变量。
只需要给UserDetailView指定一个自定义的context_object_name,比如viewed_user:
class UserDetailView(DetailView): model = User template_name = 'blog/user_detail.html' context_object_name = 'viewed_user' # 新增这一行
之后在user_detail.html模板中,用{{ viewed_user }}指代当前查看的用户,导航栏里的{{ user }}依然是当前登录用户。
方法2:在模板中直接使用request.user
如果不想修改视图代码,可以直接在base.html的导航栏里用{{ request.user }}代替{{ user }},确保始终获取当前登录用户:
{% if request.user.is_authenticated %} <a class="nav-item nav-link" href="{% url 'post-create' %}">New Post</a> <a class="nav-item nav-link" href="{% url 'user-detail' request.user.id %}">{{ request.user.username }}</a> <a class="nav-item nav-link" href="{% url 'logout-page' %}">Logout</a> {% endif %}
注意:需确保项目配置中'django.contrib.auth.middleware.AuthenticationMiddleware'中间件已启用,这样request.user才能在模板中正常访问。
方法3:重写get_context_data方法
也可以通过重写UserDetailView的get_context_data方法,明确保留当前登录用户的上下文变量,同时自定义查看用户的变量名:
class UserDetailView(DetailView): model = User template_name = 'blog/user_detail.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 将查询到的用户重命名为viewed_user context['viewed_user'] = context.pop('user') # 确保当前登录用户以current_user存在 context['current_user'] = self.request.user return context
之后模板里用{{ viewed_user }}显示被查看的用户,{{ current_user }}或{{ user }}显示当前登录用户。
内容的提问来源于stack exchange,提问作者lumba

