NoReverseMatch...Reverse for 'rxindex' not found.

Another NoReverseMatch question, unresolved after viewing quite a few similar issues. I’m still very close to the bottom of my Python learning curve but have built a few sites with PHP\Symfony. There I had no problems with reverse lookup of named urls (thanks to Twig). So I expect the solution is something simple but somehow overlooked.

My issue shows up with a menu that includes this link:

<a class="nav-link" href="{% url 'rxindex' %}">Manage reactions</a>

and the oft quoted error ensues when a page containing the menu is rendered. If instead the menu item is:

<a class="nav-link" href="{% url 'rxindex' as the_url %}">Manage reactions</a>

the page is rendered without error, but the rendered html is:

<a class="nav-link" href="">Manage reactions</a>

project’s urls.py:

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('meal/', include('meals.urls')),
    path('reaction/', include( 'reactions.urls')),
    path('admin/', admin.site.urls),
]

app reactions’ urls.py

from django.urls import path
from . import views
from django.conf import settings
from django.conf.urls.static import static

app_name = "reactions"

urlpatterns = [
    path('view/', views.rxIndex, name='rxIndex'),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

You have:

but your definition is:

and the two names don’t match.

Python is case-sensitive.

Ken,

Great catch!. Unfortunately, fixing the text did not solve the problem. I get the same result with other url tags where text match between views & menu items.

George

We’ll need to see those specific examples then. There may be other, different-but-similar issues with those items. It also helps to get the complete traceback being generated. There are cases where the root issue is not the last item in the stack.

Ken,

Thanks for getting back to me so quickly.

Traceback is below. I’m guessing what is meant by “… root issue is not the last item in the stack.” It’s likely the source of my woes, but I really need to understand what you mean. Can you direct me to some illuminating resource(s)?

Traceback:

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/meal/

Django Version: 4.1.5
Python Version: 3.11.1
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'meals',
 'reactions',
 'bootstrap5']
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 G:\workspace\python-land\diet\meals\templates\default\_apps_menu.html, error at line 14
   Reverse for 'rxIndex' not found. 'rxIndex' is not a valid view function or pattern name.
   4 :         <li class="nav-item">
   5 :             <a class="nav-link active" href="{% url 'home' as the_url %}">Home</a>
   6 :         </li>
   7 :         <li class="nav-item">
   8 :             <a class="nav-link" href="{% url 'mealIncludedFood'  as the_url %}">Manage meals</a>
   9 :         </li>
   10 :         <li class="nav-item">
   11 :             <a class="nav-link" href="{% url 'home' as the_url %}">Manage foods</a>
   12 :         </li>
   13 :         <li class="nav-item">
   14 :             <a class="nav-link" href=" {% url 'rxIndex' %} ">Manage reactions</a>
   15 :         </li>
   16 :     </ul>
   17 : </nav>

Traceback (most recent call last):
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "G:\workspace\python-land\diet\meals\views.py", line 14, in home
    return render(request, 'default/index.html', context)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\shortcuts.py", line 24, in render
    content = loader.render_to_string(template_name, context, request, using=using)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\loader.py", line 62, in render_to_string
    return template.render(context, request)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\backends\django.py", line 62, in render
    return self.template.render(context)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 175, in render
    return self._render(context)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 167, in _render
    return self.nodelist.render(context)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 966, in render_annotated
    return self.render(context)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\loader_tags.py", line 157, in render
    return compiled_parent._render(context)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 167, in _render
    return self.nodelist.render(context)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 966, in render_annotated
    return self.render(context)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\defaulttags.py", line 322, in render
    return nodelist.render(context)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 966, in render_annotated
    return self.render(context)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\loader_tags.py", line 208, in render
    return template.render(context)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 177, in render
    return self._render(context)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 167, in _render
    return self.nodelist.render(context)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\base.py", line 966, in render_annotated
    return self.render(context)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\template\defaulttags.py", line 472, in render
    url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\urls\base.py", line 88, in reverse
    return resolver._reverse_with_prefix(view, prefix, *args, **kwargs)
  File "G:\workspace\python-land\diet\.venv\Lib\site-packages\django\urls\resolvers.py", line 828, in _reverse_with_prefix
    raise NoReverseMatch(msg)

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

Nope, there’s nothing hidden there. It was worth checking, but nothing jumps out at me in that block.
(This traceback is a standard Python traceback. Any good Python reference that discusses exception handling would help.)

So looking at this more deeply, I see where you have:

This app_name defines a namespace for your urls. This means you need to specify the namespace as part of the url you are trying to reverse:

e.g. {% url 'reactions:rxIndex' %}

This would be true for any URL entry in a urls.py file with an app_name attribute defined.

This is all discussed in great detail at URL dispatcher | Django documentation | Django

Thanks.

I find I’m floundering - I’m trying to reproduce Symfony behavior in Django and it’s escaping me. Here’s where I want to be:

  • In each app (e.g., so far just meals & reactions) a set of templates appropriate to the models in those apps. Note: I think I’ve gotten this.

  • In each template, regardless of app, include a base template (e.g., {% extends "base.html" %}, where the text between the %s is constant and not dependent on the app. The base template will include an {% if ...%}...{% else %}...{% endif %} which queries the current url. The options inside would render menu options like those containing the {% url 'foo:bar' %} links that got this whole thread started. Q: Where would such templates go? A unique app? Project level?

  • At the domain level (e.g. in development, 127.0.0.1:8000/, render a home page. Q: Does this require an entry in the project level urls.py that looks like this: path('', include('some_app.urls')?

Thanks for your patience & wisdom.

Side note: This may sound “trite” or “trivial”, but Django isn’t Symfony.

What I really mean by that is that there are a number of fundamental differences in how you want to implement a solution for a requirement between the two. It’s ok to say you want to provide the same features as something written in Symfony, just be aware that your approach for the implementation is likely to be very different.

Disclaimer: My usage of Drupal, Wordpress, and Joomla mostly pre-dates what I believe to be the widespread adoption of Symfony. So while I don’t have a lot of direct experience with Symfony, I think I’m familiar enough with PHP frameworks to where I believe the parallels hold.

Not a problem - but in the “Django world”, the templates in an app should be more related to the views that render them rather than the models being rendered.

A view can query and render models from any app, such as the User, Group, and Permission models from django.contrib.auth.

However, the directory search method for templates means it doesn’t really matter in what app a template resides, unless you’re trying to override existing templates from other apps, in which case the search order is significant. (See How to override templates | Django documentation | Django)

This is where you need to turn your perspective “inside out”. Your template shouldn’t be querying anything. Your view (and possibly a context processor) should be identifying what data is to be rendered in a template, and passing that along to the rendering engine through the context.

You want to do the absolute minimum amount of work in the template. All the heavy lifting belongs in the views. Build your data structure in your views and let the template just render it.

When you have a common process (such as a dynamic menu) that needs to provide data in the context for every template, you’ll want to implement a context_processor. See The Django template language: for Python programmers | Django documentation | Django

You don’t need to include an app’s urls for that. You could define the view reference directly in your root urls.py file. I just spot-checked four projects - we have a variety. Two directly reference the view, one has the include, and the fourth does a redirect (See Base views | Django documentation | Django).

Ken,

Thanks so much for this. It’s been quite clear to me for a while now that my Symfony-infused thinking needs to be reeled in. I much appreciate your comments. I’ll see what I can do with this.

Again, many thanks for your time and effort. Much obliged.

George

Any time - and if you get stuck, we’ll still be here.