我正在拔头发,试图理解为什么我遇到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$']
答案 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
之类的下划线)