Django音乐应用创建专辑后跳转详情页遇NoReverseMatch错误求助
Django音乐应用跳转错误排查解决
问题场景
开发基于Django的音乐应用,期望创建新专辑后自动跳转到该专辑详情页,但使用reverse生成跳转链接时出现NoReverseMatch错误。
错误信息
Traceback (most recent call last): File "C:\Users\Sanath\anaconda3\lib\site-packages\django\core\handlers\exception.py", line 55, in inner response = get_response(request) File "C:\Users\Sanath\anaconda3\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "C:\Users\Sanath\anaconda3\lib\site-packages\django\views\generic\base.py", line 103, in view return self.dispatch(request, *args, **kwargs) File "C:\Users\Sanath\anaconda3\lib\site-packages\django\views\generic\base.py", line 142, in dispatch return handler(request, *args, **kwargs) File "C:\Users\Sanath\anaconda3\lib\site-packages\django\views\generic\edit.py", line 184, in post return super().post(request, *args, **kwargs) File "C:\Users\Sanath\anaconda3\lib\site-packages\django\views\generic\edit.py", line 153, in post return self.form_valid(form) File "C:\Users\Sanath\anaconda3\lib\site-packages\django\views\generic\edit.py", line 136, in form_valid return super().form_valid(form) File "C:\Users\Sanath\anaconda3\lib\site-packages\django\views\generic\edit.py", line 65, in form_valid return HttpResponseRedirect(self.get_success_url()) File "C:\Users\Sanath\anaconda3\lib\site-packages\django\views\generic\edit.py", line 125, in get_success_url url = self.object.get_absolute_url() File "C:\Users\Sanath\Desktop\website\music\models.py", line 12, in get_absolute_url return reverse('music:detail',kwargs = {'pk' : self.pk}) File "C:\Users\Sanath\anaconda3\lib\site-packages\django\urls\base.py", line 88, in reverse return resolver._reverse_with_prefix(view, prefix, *args, **kwargs) File "C:\Users\Sanath\anaconda3\lib\site-packages\django\urls\resolvers.py", line 828, in _reverse_with_prefix raise NoReverseMatch(msg) django.urls.exceptions.NoReverseMatch: Reverse for 'detail' with keyword arguments '{'pk': 11}' not found. 1 pattern(s) tried: ['music/(?P<album_id>[0-9]+)/\\Z']
相关代码文件
urls.py
from django.urls import path from . import views app_name = 'music' urlpatterns = [ #music/ path('', views.index,name = 'index'), #music/71/ path('<int:album_id>/', views.detail,name = 'detail'), path("register/",views.UserFormView.as_view(),name = 'register'), path("album/add/",views.albumcreate.as_view(),name = 'album-add'), #url pattern for the view albumcreate ]
models.py
from django.db import models from django.urls import reverse # Create your models here. class album(models.Model): #inherit from models.Model artist = models.CharField(max_length=250) #when migrated to db it will be a column with the same name automatically(here it is variables #charfield ,foreignkey is datatype album_title = models.CharField(max_length=500) genre = models.CharField(max_length=100) album_logo = models.CharField(max_length=1000) def get_absolute_url(self): return reverse('music:detail',kwargs = {'pk' : self.pk}) #returns the detail page of the album we just created def __str__(self): return self.album_title+'-'+self.artist#string representation of obj class songs(models.Model): #songs needs to be part of an album album = models.ForeignKey(album,on_delete=models.CASCADE) #bts another column with unique id 1st album id 1 2nd album id 2 and so on #let pk of red = 1 then a song of that album will have fk as 1 so that they are linked #when ever we delete the ablum red all the songs in the album should be deleted hence delete file_type= models.CharField(max_length=10) #mp3etc song_title = models.CharField(max_length=250) def __str__(self): return self.song_title
views.py
from django.http import HttpResponse from .models import album from django.shortcuts import render,redirect from django.contrib.auth import login,logout,authenticate from django.http import Http404 from django.views.generic import View from .forms import UserForm from django.views.generic.edit import CreateView,UpdateView,DeleteView # form to create new ,deleting,updating obj def index(request): all_albums = album.objects.all() ''' html ='' for album1 in all_albums: path='/music/' + str(album1.id) + '/' html += '<a href="' + path + '">' + album1.album_title + '</a><br>' ''' # template = loader.get_template('music/index.html') context = { 'all_albums': all_albums, } #return HttpResponse(template.render(context,request)) #same thing as i did in alb1 code excpet i have done it though html file to prevent making a mess here return render(request,'music/index.html',context) #same as above but using render shortcut which internally creates http response def detail(request, album_id): try: alb = album.objects.get(pk=album_id) except album.DoesNotExist: raise Http404("album does not exist") return render(request,'music/detail.html',{ 'alb': alb}) #not using context because we make use of only one album at one time and there ia no iterating over class UserFormView(View): form_class = UserForm template_name = 'music/reg_form.html' def get(self,request): # when ever user requests from this form this fn is called #display a blank form form = self.form_class(None) # nothing is present we have to input it return render(request,self.template_name,{form:form}) #self. teemp name = where u want to return ,what html# def post(self,request): # when ever user submits the above form this fn is called form = self.form_class(request.POST) # what ever is entered in get is posted if form.is_valid(): user= form.save(commit=False) #storing itlocally not yet commited to db #cleaned normalized data(so that everyone uses the gemeral format and can be entered into the db properly username = form.cleaned_data['username'] password = form.cleaned_data['password'] user.set_password(password) #method to set password we cannot do like user.password = 'raj' or = password user.save() # return user obj id credentials are correct user = authenticate(username=username,password = password) #what the above fun does it that it takes the username and pwd and chcecks with the db is they are an actual user if user is not None: #for confirming above fn if user.is_active: login(request,user) #logged in to the website #request.user.username return redirect('music:index') return render(request,self.template_name,{form:form}) #new classsthat creates the form view for get abs url fn class albumcreate( CreateView ): #using models and not by admin or shell queries but in the webpage itself model = album fields = ['artist','album_title','genre','album_logo'] #we havent specified template name cuz _form is the default file it is going to look at
问题原因
错误提示明确:reverse尝试用pk参数匹配detail视图,但URL模式里定义的参数名是album_id,两者不匹配,导致无法生成正确的跳转链接。
解决方法
两种可行修复方式,选其一即可:
方式一:修改get_absolute_url中的参数名
在models.py的album类里,把reverse的kwargs里的pk改成album_id:
def get_absolute_url(self): return reverse('music:detail', kwargs={'album_id': self.pk})
方式二:修改URL模式中的参数名
在urls.py里,把详情页的URL参数从album_id改成pk,同时同步修改views.py中detail函数的参数:
- urls.py修改:
path('<int:pk>/', views.detail, name='detail'),
- views.py修改:
def detail(request, pk): try: alb = album.objects.get(pk=pk) except album.DoesNotExist: raise Http404("album does not exist") return render(request,'music/detail.html',{ 'alb': alb})
两种方式都能解决参数不匹配问题,完成后创建新专辑即可正常跳转到详情页。
内容的提问来源于stack exchange,提问作者Sanath
相关产品推荐
相关产品推荐

