Django重定向NoReverseMatch

时间:2018-08-30 15:09:34

标签: python django django-templates django-views

我正在拔头发,试图理解为什么我遇到NoReverseMatch错误。

我正试图让它添加一个参与者并返回到特定研究的参与者列表。我还试图使后退按钮正常工作,但同时也出现NoReverseMatch错误。

网址

urlpatterns = [
    path('', views.homepage, name='homepage'),
    path('studies/', views.studylist, name='studylist'),
    path('studies/add_study', views.add_study, name='add_study'),
    path('studies/<int:id>', views.study_update, name='study_edit'),
    path('studies/<int:id>/participants', views.participantlist, name='participantlist'),
    path('studies/<int:id>/participants/add_participant', views.add_participant, name='add_participant')]

观看次数

def participantlist(request, id):
    participant_list = Participant.objects.filter(study_id=id)
    return render(request, 'databank/participants.html',
        {'participantlist':participant_list, 'study_id':id})

def add_participant(request, id):
    if request.method == "POST":
        form = ParticipantForm(request.POST)
        if form.is_valid():
            participant_item = form.save(commit=False)
            participant_item.study_id = id
            participant_item.save()
            return HttpResponseRedirect(reverse('participantlist', args=(id,)))
    else:
        form = ParticipantForm()
    return render(request, 'studies/add_participant.html', {'form': form})

模板

<!DOCTYPE html>
<html>
<head>
    <title>Study Participant</title>
</head>
<body>
<h1>Add or Edit Participant</h1>
<p>Please fill in the required information and click save to add a participant</p>
<form method="POST" action=" ">
{% csrf_token %}
<table>
{{ form }}
</table>
<br>
  <input type="submit" value="Save">
</br>
</form>
<br />
<form action="{% url 'participantlist' %}">
<input type="submit" value="Back" />
</form>
</body>
</html>

NoReverseMatch

Reverse for 'participantlist' with arguments '('',)' not found. 1 pattern(s) tried: ['studies/(?P<id>[0-9]+)/participants$']

Environment:


Request Method: GET
Request URL: http://localhost:8000/studies/1/participants/add_participant

Django Version: 2.1
Python Version: 3.7.0
Installed Applications:
['databank.apps.DatabankConfig',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles']
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:\Projects\mysite\databank\templates\studies\add_participant.html, error at 
line 19
Reverse for 'participantlist' with no arguments not found. 1 pattern(s) 
tried: 
['studies/(?P<id>[0-9]+)/participants$']
9 : <form method="POST" action=" ">
10 :   {% csrf_token %}
11 :   <table>
12 :   {{ form }}
13 :   </table>
14 :     <br>
15 :       <input type="submit" value="Save">
16 :     </br>
17 :   </form>
18 :   <br />
19 :   <form action=" {% url 'participantlist' %} ">
20 :     <input type="submit" value="Back" />
21 :   </form>
22 :   </body>
23 : </html>
24 : 

Traceback:

File "C:\Projects\myvenv\lib\site-packages\django\core\handlers\exception.py" 
in inner
34.             response = get_response(request)

File "C:\Projects\myvenv\lib\site-packages\django\core\handlers\base.py" in 
_get_response
 126.                 response = self.process_exception_by_middleware(e, 
request)

File "C:\Projects\myvenv\lib\site-packages\django\core\handlers\base.py" in 
_get_response
 124.                 response = wrapped_callback(request, *callback_args, 
**callback_kwargs)

File "C:\Projects\mysite\databank\views.py" in add_participant
70.     return render(request, 'studies/add_participant.html', {'form': 
form})

File "C:\Projects\myvenv\lib\site-packages\django\shortcuts.py" in render
36.     content = loader.render_to_string(template_name, context, request, 
using=using)

File "C:\Projects\myvenv\lib\site-packages\django\template\loader.py" in 
render_to_string
62.     return template.render(context, request)

File "C:\Projects\myvenv\lib\site- 
packages\django\template\backends\django.py" 
in render
61.             return self.template.render(context)

File "C:\Projects\myvenv\lib\site-packages\django\template\base.py" in render
171.                     return self._render(context)

File "C:\Projects\myvenv\lib\site-packages\django\template\base.py" in 
_render
163.         return self.nodelist.render(context)

File "C:\Projects\myvenv\lib\site-packages\django\template\base.py" in render
937.                 bit = node.render_annotated(context)

File "C:\Projects\myvenv\lib\site-packages\django\template\base.py" in 
render_annotated
904.             return self.render(context)

File "C:\Projects\myvenv\lib\site-packages\django\template\defaulttags.py" in 
render
442.             url = reverse(view_name, args=args, kwargs=kwargs, 
current_app=current_app)

File "C:\Projects\myvenv\lib\site-packages\django\urls\base.py" in reverse
90.     return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, 
**kwargs))

File "C:\Projects\myvenv\lib\site-packages\django\urls\resolvers.py" in 
_reverse_with_prefix
  622.         raise NoReverseMatch(msg)

Exception Type: NoReverseMatch at /studies/1/participants/add_participant
Exception Value: Reverse for 'participantlist' with no arguments not found. 1 
pattern(s) tried: ['studies/(?P<id>[0-9]+)/participants$']

1 个答案:

答案 0 :(得分:0)

您的问题是您试图获取具有可变字段的路径的URL(在路径定义中,您试图捕获ID(path('studies/<int:id>/participants', [...])),但是当您请求反向URL时使用路径名没有匹配项,因为该路径实际上不存在没有ID的URL,换句话说,告诉Django,所有参与者列表必须在URL中具有ID,但是您在尝试获取ReverseMatch时未指定

您可以告诉Django模板引擎其参数,以使用以下语法找到匹配项:

{% url 'path_name' keyword_arg=keyword_val %}

因此,您的实现应为:

{% url 'participantlist' id=the_id %}

the_id(或您为此确定的其他任何名称)中,您必须在Django渲染请求中设置一个变量,并传递适当的ID。我看到您可能已经将该变量作为study_id传递了,但我不确定,因为我不知道哪个ID代表什么。无论如何,总的来说,我认为您在弄错应用逻辑。看来您正在发送将参与者添加到负责检索参与者列表的URL的操作,而该时间应该是add_participant

编辑

我不建议在您的视图中混用添加编辑。添加应该针对尚未创建且没有自己的ID的实例(在您的情况下,参与者具有ID以及包含参与者的其他结构,具有不同的ID列表)。为了添加参与者,您将转到一个表单,该表单没有要添加的参与者的任何预设信息(除非您明确决定要这样做),而编辑应该是一个不同的URL映射,该映射要求现有参与者的ID以便对其进行编辑(以及您决定登录的凭据)。

两个路径都应该接受get和post;这个你说对了。 Get呈现一个表单,但要注意:表单的动作应与get的URL相同;只有当您发布数据时,视图的逻辑才会感知并采取适当的措施。

在涉及数据编辑时,您可以选择将GET和POST URL分开,但是通常不建议这样做,因为您可能会将它与获取已有数据的操作(而不是获取用于编辑表单的表单)混合使用数据)。

最后一点要澄清:您的participantlist 1 路径用于获取参与者列表,而不是用于编辑任何参与者的数据。如果您只能从一个参与者那里获取信息,则可能是

path('studies/<int:study_id>/participants/<int:participant_id>', views.get_participant, name='get_participant')

同时编辑参与者(使用GET和POST方法)的路径为:

path('studies/<int:study_id>/participants/<int:participant_id>/edit', views.edit_participant, name='edit_participant')

脚注

1 (从样式上看,最好在下划线处添加participant_list之类的下划线)