Django错误:NoReverseMatch

时间:2016-09-07 19:57:57

标签: python django

我正在使用Django 1.10和python 3.4

准确的错误是

NoReverseMatch at /movies/movie/Twilight/
Reverse for 'movie-details' with arguments '(8,)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['movies/movie/(?P<movie_id>\\d+)|(?P<movie_name>[a-zA-Z\\ ]+)/$']

错误是由以下行造成的:{em>模板 moviesrating / select_movie.html

中的{% url 'moviesrating:movie-details' movie.id %}

在文件 moviesrating / urls.py 中,正确包含在主网址文件中,有以下几行:

app_name = 'moviesrating'

urlpatterns = [
    url(r'^movie/(?P<movie_id>\d+)|(?P<movie_name>[a-zA-Z\ ]+)/$', view_movie, name = 'movie-details'),
]

引用 moviesrating / views.py 中的函数 view_movie

def view_movie(request, movie_id, movie_name):
    if movie_id:
        movie = get_object_or_404(Movie, pk = movie_id)
    elif movie_name:
        try:
            movie = get_object_or_404(Movie, name = movie_name)
        except MultipleObjectsReturned: # There are two movies named 'Twilight'
            movies = get_list_or_404(Movie, name = movie_name)
            return render(request, "moviesrating/select_movie.html", {'movies': movies})
    else:
        movie = None
    return render(request, "moviesrating/movie.html", {'movie': movie})

网址 / movies / movie /...的目的是显示按名称或ID找到的电影,具体的网址格式来自此需求。

关键是错误显示即使它没有找到反向匹配,它也会找到正确的网址格式,所以我觉得这个模式并不匹配。然后我尝试将行更改为:

{% url 'moviesrating:movie-details' movie.id %}
{% url 'moviesrating:movie-details' movie_id=movie.id movie_name=None %}
{% url 'moviesrating:movie-details' movie.id None %}
{% url 'moviesrating.views.view_movie' movie.id %}
{% url 'moviesrating.views.view_movie' movie_id=movie.id %}
{% url 'moviesrating.views.view_movie' movie_id=movie.id movie_name=None %}

但他们都没有工作。

查看浏览器中的链接(例如 http:// localhost:8081 / movies / movie / 8 )是有效的,因此不是导致问题的页面。< / p>

此时我真的无法理解这个问题,我已经按照django docs中解释的段落阅读了已经提出的很多问题,但没有一个问题能解决我的问题。 / p>

如果有什么不清楚或需要更多信息,请告诉我,我会编辑帖子。感谢

以下是错误的完整堆栈跟踪:

Environment:


Request Method: GET
Request URL: http://localhost:8081/movies/movie/Twilight/

Django Version: 1.10.1
Python Version: 3.5.2
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'todolist.apps.TodolistConfig',
 'moviesrating.apps.MoviesratingConfig']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']


Template error:
In template C:\Users\fra\Programmazione\Python\myserver\moviesrating\templates\moviesrating\select_movie.html, error at line 12
   Reverse for 'movie-details' with arguments '(8,)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['movies/movie/(?P<movie_id>\\d+)|(?P<movie_name>[a-zA-Z\\ ]+)/$']   2 : <html>
   3 : <head>
   4 : <meta charset="ISO-8859-1">
   5 : <title>Choice your movie</title>
   6 : </head>
   7 : <body>
   8 : <h2>Choice of which movie named {{ movies.0.name }} would you see the details</h2>
   9 : 
   10 : <ul>
   11 : {% for movie in movies %}
   12 :     <li> {% url 'moviesrating:movie-details' movie.id %} </li>
   13 :     <li><a href="{{ movie_url }}">{{ movie.name }} del {{ movie.year }} diretto da {{ movie.director }}</a></li>
   14 : {% endfor %}
   15 : </ul>
   16 : </body>
   17 : </html>
   18 : 

Traceback:

File "C:\Users\fra\Programmazione\Python\myserver\moviesrating\views.py" in view_movie
  31.             movie = get_object_or_404(Movie, name = movie_name)

File "C:\Program Files (x86)\Python\lib\site-packages\django\shortcuts.py" in get_object_or_404
  85.         return queryset.get(*args, **kwargs)

File "C:\Program Files (x86)\Python\lib\site-packages\django\db\models\query.py" in get
  389.             (self.model._meta.object_name, num)

During handling of the above exception (get() returned more than one Movie -- it returned 2!), another exception occurred:

File "C:\Program Files (x86)\Python\lib\site-packages\django\core\handlers\exception.py" in inner
  39.             response = get_response(request)

File "C:\Program Files (x86)\Python\lib\site-packages\django\core\handlers\base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "C:\Program Files (x86)\Python\lib\site-packages\django\core\handlers\base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\Users\fra\Programmazione\Python\myserver\moviesrating\views.py" in view_movie
  34.             return render(request, "moviesrating/select_movie.html", {'movies': movies})

File "C:\Program Files (x86)\Python\lib\site-packages\django\shortcuts.py" in render
  30.     content = loader.render_to_string(template_name, context, request, using=using)

File "C:\Program Files (x86)\Python\lib\site-packages\django\template\loader.py" in render_to_string
  68.     return template.render(context, request)

File "C:\Program Files (x86)\Python\lib\site-packages\django\template\backends\django.py" in render
  66.             return self.template.render(context)

File "C:\Program Files (x86)\Python\lib\site-packages\django\template\base.py" in render
  208.                     return self._render(context)

File "C:\Program Files (x86)\Python\lib\site-packages\django\template\base.py" in _render
  199.         return self.nodelist.render(context)

File "C:\Program Files (x86)\Python\lib\site-packages\django\template\base.py" in render
  994.                 bit = node.render_annotated(context)

File "C:\Program Files (x86)\Python\lib\site-packages\django\template\base.py" in render_annotated
  961.             return self.render(context)

File "C:\Program Files (x86)\Python\lib\site-packages\django\template\defaulttags.py" in render
  209.                     nodelist.append(node.render_annotated(context))

File "C:\Program Files (x86)\Python\lib\site-packages\django\template\base.py" in render_annotated
  961.             return self.render(context)

File "C:\Program Files (x86)\Python\lib\site-packages\django\template\defaulttags.py" in render
  439.             url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app)

File "C:\Program Files (x86)\Python\lib\site-packages\django\urls\base.py" in reverse
  91.     return force_text(iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs)))

File "C:\Program Files (x86)\Python\lib\site-packages\django\urls\resolvers.py" in _reverse_with_prefix
  392.             (lookup_view_s, args, kwargs, len(patterns), patterns)

Exception Type: NoReverseMatch at /movies/movie/Twilight/
Exception Value: Reverse for 'movie-details' with arguments '(8,)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['movies/movie/(?P<movie_id>\\d+)|(?P<movie_name>[a-zA-Z\\ ]+)/$']

3 个答案:

答案 0 :(得分:1)

Django的reverse()无法处理捕获组之外的析取模式(使用|)。这是你希望有人在过去10年左右在某处修好的事情之一,但这个限制已经在since 1.0左右。

解决方法是将模式拆分为两种模式:

urlpatterns = [
    url(r'^movie/(?P<movie_id>\d+)/$', view_movie, name='movie-details'),
    url(r'^movie/(?P<movie_name>[a-zA-Z\ ]+)/$', view_movie, name='movie-details'),
]

您需要为这两个参数添加默认值:

def view_movie(request, movie_id=None, movie_name=None):
    ...

答案 1 :(得分:0)

您只向视图发送一个参数,但它需要两个参数。如果你想坚持一个可以解释为id或名字的,为什么不接受字母数字参数

urlpatterns = [
url(r'^movie/(?P<movie_id>[A-z0-9]+)/$', view_movie, name = 'movie-details'),
]

然后在你的视图中检查它是哪一个,以便你知道你是否应该将它视为id或名称

def view_movie(request, movie_id):
     try: 
         int(movie_id)
         movie_name = False
    except:
         movie_name = True

    if not movie_name:
        movie = get_object_or_404(Movie, pk = movie_id)
    elif movie_name:

    # etc.

答案 2 :(得分:0)

您可以在捕获组周围添加括号:

urlpatterns = [
    url(r'^movie/((?P<movie_id>\d+)|(?P<movie_name>[a-zA-Z\ ]+))/$', view_movie, name = 'movie-details'),
]

并添加默认值以查看参数:

def view_movie(request, movie_id=None, movie_name=None):
    if movie_id:
        return HttpResponse('1')
    if movie_name:
        return HttpResponse('2')

Idk为什么,但我已经在我的项目中尝试了这个并且它有效。