pythondjangodjango-urlsdjango-url-reverse

Django URL tag not working - NoReverseMatch


I know we aren't supposed to use stackoverflow for debugging but i've been trying to fix this in the last 10 hours and I feel hopeless, my apologies.

#main project urls.py:
urlpatterns = [
    ...
    path('accounts/',include('employee.urls')),
    ...
]...

#employee.urls:
urlpatterns = [
    ...
    path('employees/', views.display_employees),
    path('edit/<str:employee_ssn>/', views.edit_employee),
    ...
]

#views.py - edit_employee being used only for testing by now
def display_employees(request):
    logged_user = request.user
    queryset = Employee.objects.filter(company=logged_user.company)
    context = {
        'employees': queryset
    }
    return render(request, 'employees.html', context)

def edit_employee(request, employee_ssn):
    context = {}
    emp = Employee.objects.filter(ssn=employee_ssn)
    
    context = {
        'employee_list': emp
    }
    return render(request, 'edit-employee.html', context)

#employees.html
<ul>
    {% for obj in employees %}
    <li>{{ obj.name }}</li>
    <li>{{ obj.ssn }}</li>
    <li>{{ obj.email }}</li>
    <li><a href="{% url '/accounts/edit/' obj.ssn %}">edit</a></li><br>
    {% endfor %}
</ul>

#edit-employee.html
<ul>
{% for obj in employee_list %}
    <li>{{ obj.name }}</li>
    <li>{{ obj.ssn }}</li>
    <li>{{ obj.email }}</li>
{% endfor %}
</ul>

When it is clicked on edit it says:

Exception Type: NoReverseMatch Exception Value: Reverse for '/accounts/edit/' not found. '/accounts/edit/' is not a valid view function or pattern name.

But if the url http://localhost:8000/accounts/edit/<employee_snn>/ is typed on the browser, edit-employee.html renders normally. It also says the error is in my base template at line 0


Solution

  • You can not use the "pattern" in the {% url … %} template tag [Django-doc]. You should give the view a name and then use this to resolve the url, so:

    urlpatterns = [
        # …
        path('employees/', views.display_employees),
        path('edit/<str:employee_ssn>/', views.edit_employee, name='edit-employee'),
        # …
    ]

    and then you can use this as parameter in the {% url … %} tag:

    <li><a href="{% url 'edit-employee' obj.ssn %}">edit</a></li><br>

    The idea of using an {% url … %} tag is that you can easily change the path patterns. As long as the name remains the same, and the parameters, it will still be able to resolve the template path.