Джанго, перенаправляющий NoReverseMatch - PullRequest
0 голосов
/ 30 августа 2018

Я вырываю волосы, пытаясь понять, почему я получаю NoReverseMatch ошибку.

Я пытаюсь заставить его добавить участника и вернуться к списку участников конкретного исследования. Я также пытаюсь заставить работать кнопку возврата, но также получаю сообщение об ошибке NoReverseMatch.

Urls

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})

Template

<!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 голосов
/ 30 августа 2018

Ваша проблема в том, что вы пытаетесь получить URL для пути, который имеет переменное поле (в своем определении пути вы пытаетесь захватить идентификатор (path('studies/<int:id>/participants', [...])), но когда вы запрашиваете обратный URL, используя имя пути не совпадает, потому что на самом деле не существует URL для этого пути, у которого нет идентификатора. Таким образом, вы говорите Django, что у всех участников списка должен быть идентификатор в URL, , но вы не указываете его при попытке получить ReverseMatch .

Вы можете указать шаблонизатору Django параметры для него, чтобы найти соответствие с этим синтаксисом:

{% url 'path_name' keyword_arg=keyword_val %}

Итак, ваша реализация будет:

{% url 'participantlist' id=the_id %}

Где the_id (или любое другое имя по вашему выбору) - это переменная, которую вы должны установить в запросе рендеринга Django, передавая соответствующий ID. Я вижу, вы, возможно, уже передали эту переменную как study_id, но я не совсем уверен, потому что я не знаю, какой идентификатор обозначает что. В любом случае, я думаю, что вы неправильно понимаете логику приложения. Похоже, вы отправляете действие по добавлению участника в URL-адрес, отвечающий за получение списка участников, когда это должно быть для add_participant.

Редактировать

Я не рекомендую смешивать , добавляя и , редактируя в ваших представлениях. Добавление должно быть сделано для экземпляра, который еще не создан и не имеет собственного идентификатора (в вашем случае, у участника есть идентификатор, а также другая структура, содержащая участников, у которой есть другой список идентификаторов). Чтобы добавить участника, вы переходите к форме, в которой нет предварительно заданной информации об участнике, которого вы хотите добавить (если вы явно не решите это сделать), тогда как редактирование должно быть другой картой URL, которая запрашивает идентификатор существующего участника. для того, чтобы отредактировать его (а также учетные данные для входа, если вы решите).

Оба пути должны принимать get и post; это ты правильно понял Get отображает форму, но слушайте: действие формы должно совпадать с URL-адресом get; только когда вы публикуете данные, логика вашего представления воспримет их и примет соответствующие меры.

При необходимости вы можете разделить 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)

...