Django通过URL传入username生成用户专属页链接遇Reverse报错的解决方法
报错原因&完整修复方案
- 触发当前报错的直接原因:
profile路由配置了必填的username参数,而你在模板里做反向链接生成时没有传入这个参数,Django自然匹配不到对应的路由规则。 - 你还有一个非常容易踩坑的路由配置隐患如果不修复,后续还会触发其他莫名其妙的bug:动态路径规则如果放在固定路径规则前面,会拦截所有后续固定路径的请求,导致功能完全失效。
第一步:修正urls.py的路由顺序
Django的路由是按代码书写顺序从上到下匹配的,你目前把<slug:username>这条动态路径放在了EditProfile/固定路径前面,会导致用户点击编辑资料按钮时,请求路径里的EditProfile被直接当成username参数值,错误命中个人主页路由。
必须把所有写死的固定路径全部放在动态参数路径的前面,修正后的配置如下:
from django.conf.urls import url from django.urls import path from django.contrib.auth import views as auth_views from . import views app_name = 'accounts' urlpatterns = [ # 所有固定路径优先配置 path('Skolar/',views.base, name= 'base'), path('Register/',views.register,name='register'), path('login/', views.my_login_view, name='login'), path('logout/',views.user_logout,name='logout'), path('EditProfile/',views.update_profile,name='editprofile'), # 动态参数路径放在所有固定路径的最后面 path('<str:username>',views.profile, name='profile'), ]
- 小提示:把
slug转换器换成str更适配用户名场景,避免因为用户名包含大写字符被slug规则匹配拦截。
第二步:修正模板里的反向链接传参
原来的跳转写法没有传入路由要求的必填username参数,直接把当前登录用户的用户名传入即可:
错误写法:
<a class="dropdown-item" href="{% url 'accounts:profile' %}">My Account</a>
修正后写法:
<a class="dropdown-item" href="{% url 'accounts:profile' request.user.username %}">My Account</a>
第三步:完善profile视图逻辑(解决其他用户主页显示错误的问题)
你当前写的profile视图完全没有使用传入的username参数,哪怕用户访问的是别人的个人主页,页面渲染的还是当前登录用户的信息,和你要做的「每个用户有专属主页」的需求完全不符。补充根据username查询对应用户的逻辑即可:
from django.shortcuts import get_object_or_404 from django.contrib.auth.models import User def profile(request, username): # 查找对应username的用户,不存在则返回404页面 target_user = get_object_or_404(User, username=username) return render(request, 'profile.html', {'target_user': target_user})
对应修改profile.html模板里的变量,把原本直接用的{{user.xxx}}全部替换成{{target_user.xxx}},就能正确展示对应访问用户的主页信息:
{% extends 'masteraccount.html' %} {% block content %} {% load static %} <link rel="stylesheet" href="{% static 'css/accountscss/profile.css'%}"> <div class=""> <div class="page-content"> <label class="name" for="NAME">NAME:</label> <p>{{target_user.first_name}} {{target_user.last_name}}</p> <label for="Email">Email:</label> <p>{{target_user.email}}</p> <label for="Twitter">Twitter:</label> <p>{{target_user.profile.twitter}}</p> <label for="Facebook">Facebook:</label> <p>{{target_user.profile.Facebook}}</p> <label for="About">About:</label> <p>{{target_user.profile.about}}</p> <label for="dob">Date of Birth:</label> <p>{{target_user.profile.dob}}</p> </div> <a href="{% url 'accounts:editprofile' %}"> <button type="button" class="btn btn-primary btn-lg">Edit Profile</button> </a> </div> {% endblock %}
可选优化
如果你希望用户不用输入用户名,直接通过固定路径就能访问自己的主页,可以单独加一条路由,和现有带username参数的路由共存即可。
内容的提问来源于stack exchange,提问作者Shreyash mishra
相关产品推荐
相关产品推荐

