NoReverseMatch Error - HTMX -

Django 5.1.1
Python 3.12.4
HTMX 1.9.12

Goal:
The table loads and the 1st record or selected record appears in the index_2.html form and
can be edited/saved and also the user can add a new record if desired.

Problem: Also see Traceback file at the end.

App loads a table with pagination while tracking page# and 1st record displayed ‘id’ then includes
{% include ‘turnover_app/index_2.html’ %}

when index_2.html page tries to load get the hated NoReverseMatch Error (see below)
NOTE: If both HTMX buttons have a hard number in the hx-get=“{% url ‘turnover_app:edit_turn’ 12 %}”
the page loads fine without issue other than I obviously cannot use the htmx buttons
If either hx-get=“{% url ‘turnover_app:edit_turn’ tologs.pk %}” has a pk var or any var in it
then NoReverseMatch Error alerts.

urls.py (partial)

path('turnover_app/', views.turnover_index, name='turnover_index'),
path('edit_turn/<int:pk>/', views.edit_turn, name='edit_turn'),  
path('turnover_index_2/<int:pk>/', views.turnover_index_2, name='turnover_index_2'),
views.py (partial)

def turnover_index(request, *args, **kwargs):
    global _TOLOG_SRCH_ID_PAGE                                          
    tologs = ToLog.objects.all().order_by(_ORDBY)                       
    parent_rcnt = tologs.count()                                        
    paginator = Paginator(tologs, _ITEMS_PER_PAGE)                      
    page_number = request.GET.get('page')                               
    page_obj = paginator.get_page(page_number)                          
    if type(page_number) == str:                                        
        conv_2_num = int(page_number)                                   
        if conv_2_num == 1:                                             
            rec_to_get = 0                                              
        else:                                                           
            rec_to_get = (conv_2_num * _ITEMS_PER_PAGE)                 
            rec_to_get = rec_to_get - _ITEMS_PER_PAGE                   
    else:   # page_number = <class 'NoneType'>                          
        conv_2_num = 1                                                  
        rec_to_get = (conv_2_num * _ITEMS_PER_PAGE)                     
        rec_to_get = rec_to_get - _ITEMS_PER_PAGE                       
    
    _TOLOG_SRCH_ID_PAGE=(tologs[rec_to_get].id)                         
    TologPkRecID = _TOLOG_SRCH_ID_PAGE                                  
    template = 'turnover_app/index.html'                                
    return render(request, template,{'TologPkRecID': TologPkRecID, 'page_obj': page_obj, 'count': tologs.count()})

def turnover_index_2(request, pk, *args, **kwargs):
    if request.method == 'GET':                                     
        tologs = get_object_or_404(ToLog, pk=pk)                    
        context = {}                                                
        context['tologs'] = tologs          
        context['form'] = ToLogForm(initial={                       
            'id': tologs.id,                                 
            'social_title': tologs.social_title,
            'ivanti_ticket' : tologs.ivanti_ticket,
            'date_time': tologs.date_time,
            'completed': tologs.completed,
            'comments' : tologs.comments,
            'noc_tech_name' : tologs.noc_tech_name,
            'entrytype' : tologs.entrytype
        })
        template = 'turnover_app/index_2.html'                     
        return render(request, template, context)                   
    else:  # POST request
        pass
		

def edit_turn(request, pk):                        
    if request.method == 'GET':  
        tolog = ToLog.objects.get(pk=pk)                              
        context = {}
        context['tolog'] = tolog
        context['form'] = ToLogForm(initial={
            'social_title': tolog.social_title,
            'ivanti_ticket': tolog.ivanti_ticket,
            'date_time': tolog.date_time,
            'completed': tolog.completed,
            'comments' : tolog.comments,
            'noc_tech_name' : tolog.noc_tech_name,
            'entrytype' : tolog.entrytype
        })
        template = 'turnover_app/index_2.html'                                              
        return render(request, template, context)  
    else:       
        tolog = ToLog.objects.get(pk=pk)
        form = ToLogForm(request.POST, instance=tolog)
        if not form.is_valid():
        if form.is_valid():
            form.save()                                                 
            template = 'turnover_app/index_2.html'
            return render(request, template, {'form': form,'tolog': tolog})
        else:
            template = 'turnover_app/index_2.html'
            return render(request, template, {'form': form,'tolog': tolog})
index.html (partial)

<div class="container-fluid">
:			:			:			:
<div id="turnList">
     {% include 'turnover_app/turnover-list.html' %}
</div>

<div id="indx_2" class="col-6 col-md-4" hx-trigger="load" hx-get="{% url 'turnover_app:turnover_index_2' pk=TologPkRecID %}" hx-target="this">
     {% include 'turnover_app/index_2.html' %}
</div>

turnover-list.html (partial)

{% if page_obj %}

        <div class="table-responsive" style="height: 640px; overflow-y: auto;">
          <table class="table table-striped w-300 ">
            <form>
:			:			:			:			:			:			:
</form>
         <tbody>
           {% for tolog in page_obj %} 
                  {% include 'turnover_app/turnover_row.html' %}
           {% endfor %}
            </tbody>
          </table>
        </div>
              {% include 'turnover_app/pagination.html' %} 
turnover_row.html (partial)
<tr>
    <td class="text-primary" style="word-wrap: break-word;min-width: 80px;max-width: 280px; cursor: pointer;"
      hx-get="{% url 'turnover_app:turnover_index_2' pk=tolog.pk %}"
      hx-target="#indx_2"
      hx-swap="#"
      hx-trigger="click">
       <u>{{ tolog.social_title }}</u>
    </td>
:				:				:				:
    <td>
      <button type="button" 
      class="btn-sm btn btn-outline-danger" 
      hx-get="{% url 'turnover_app:delete_turn' tolog.pk %}" 
      hx-target="#turnList" 
      hx-confirm="Are you sure you wish to delete?" 
      style="cursor: pointer;">
      DEL
      </button>
    </td>
  </tr>

index_2.html (partial)

<div class="container-fluid">
    <form> 
        <div class="card mb-3" style="max-width:600px; min-width:600px;">
            <div class="card-body">
              <p class="card-text">Record Detail - TurnOver Log</p>
              <div class="form-floating mb-1 w-75">
                {% render_field form.social_title class="form-control" style="background-color: rgba(0,0,255,.1)" placeholder=form.text.label  %}
                <label for="id_social_title">Social Title:*</label>
                {% for error in form.social_title.errors %}
                  <span class="text-danger">{{ error }}</span>
                {% endfor %}
              </div>
:				:				:				:				:
                  <div>
                    <button type="button"
                      class="btn-sm btn btn-outline-danger" 
                      hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
                      hx-post="{# url 'turnover_app:create_turn #}"
                      hx-target="#" 
                      >
                      AddNew (no-op)
                    </button>
                            
                    <button type="button"
                      class="btn-sm btn btn-outline-primary" 
                      hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
                      hx-get="{% url 'turnover_app:edit_turn' 12 %}"
                      hx-target="#" 
                      >
                      Edit (testing)
                    </button>
------Traceback -------

Environment:

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

Django Version: 5.1.1
Python Version: 3.12.4
Installed Applications:
['student',
 'compressor',
 'hyperapp',
 'todo_app',
 'turnover_app',
 'mybook',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'home_app',
 'crispy_forms',
 'crispy_bootstrap5',
 'console_app',
 'django_bootstrap5',
 'user.apps.UserConfig',
 'django_tables2',
 'debug_toolbar',
 'django_htmx',
 'htmx',
 'singlepage',
 'import_export',
 'django_filters',
 'widget_tweaks',
 'rest_framework']
Installed Middleware:
['debug_toolbar.middleware.DebugToolbarMiddleware',
 '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',
 'django_htmx.middleware.HtmxMiddleware',
 'whitenoise.middleware.WhiteNoiseMiddleware']


Template error:
In template C:\Users\EAI24909\OneDrive - Epson America\Desktop\Python Projects\epson\.epsonVE\enoc_proj\turnover_app\templates\turnover_app\index_2.html, error at line 86
   Reverse for 'edit_turn' with arguments '('',)' not found. 1 pattern(s) tried: ['turnover_app/edit_turn/(?P<pk>[0-9]+)/\\Z']
   76 :                       hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
   77 :                       hx-post="{# url 'turnover_app:create_turn #}"
   78 :                       hx-target="#" 
   79 :                       >
   80 :                       AddNew (no-op)
   81 :                     </button>
   82 :                             
   83 :                     <button type="button"
   84 :                       class="btn-sm btn btn-outline-primary" 
   85 :                       hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
   86 :                       hx-get=" {% url 'turnover_app:edit_turn' tologs.pk %} "
   87 :                       hx-target="#" 
   88 :                       >
   89 :                       Edit (testing)
   90 :                     </button>
   91 :                     
   92 : 
   93 :                   </div>
   94 :                   <hr>
   95 : 
   96 :                   <div class="table-responsive" style="height: 200px; overflow-y: auto;">


Traceback (most recent call last):
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\OneDrive - Epson America\Desktop\Python Projects\epson\.epsonVE\enoc_proj\turnover_app\views.py", line 130, in turnover_index
    return render(request, template,{'TologPkRecID': TologPkRecID, 'page_obj': page_obj, 'count': tologs.count()})
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\shortcuts.py", line 25, in render
    content = loader.render_to_string(template_name, context, request, using=using)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\template\loader.py", line 62, in render_to_string
    return template.render(context, request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\template\backends\django.py", line 107, in render
    return self.template.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\template\base.py", line 171, in render
    return self._render(context)
           ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\test\utils.py", line 114, in instrumented_test_render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\template\base.py", line 1008, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\template\base.py", line 969, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\template\loader_tags.py", line 159, in render
    return compiled_parent._render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\test\utils.py", line 114, in instrumented_test_render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\template\base.py", line 1008, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\template\base.py", line 969, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\template\loader_tags.py", line 65, in render
    result = block.nodelist.render(context)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\template\base.py", line 1008, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\template\base.py", line 969, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\template\loader_tags.py", line 210, in render
    return template.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\template\base.py", line 173, in render
    return self._render(context)
           ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\test\utils.py", line 114, in instrumented_test_render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\template\base.py", line 1008, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\template\base.py", line 969, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\template\defaulttags.py", line 480, in render
    url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\urls\base.py", line 88, in reverse
    return resolver._reverse_with_prefix(view, prefix, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\EAI24909\.virtualenvs\.epsonVE-iknzfel_\Lib\site-packages\django\urls\resolvers.py", line 831, in _reverse_with_prefix
    raise NoReverseMatch(msg)
    ^^^^^^^^^^^^^^^^^^^^^^^^^

Exception Type: NoReverseMatch at /turnover_app/turnover_app/
Exception Value: Reverse for 'edit_turn' with arguments '('',)' not found. 1 pattern(s) tried: ['turnover_app/edit_turn/(?P<pk>[0-9]+)/\\Z']

are you sure set app_name in urls.py?

Hi,
Yes it was set. The name is turnover_app. You can also see it in use in the htmx button on the index_2.html page hx-get url turnover_app: … i have written many other apps without much issues. This is the 1st where I’m using 2 containers side by side and using an include with htmx control linking them. It seems to flow back to there. I’m missing something. I really appreciate you responding to my issue. Thank you so much.

you use include template in for tolog in page_obj, but template call tologs.pk.

check \turnover_app\templates\turnover_app\index_2.html.

I think that index_2.html is being included directly, without any context being passed to it. The hx-get attribute is set up to load the content via HTMX, but the initial render of the page is trying to include index_2.html before that HTMX request happens.

Yes you are correct. I removed the include and re-targeted the htmx to a new id in index_2.html page and works good now.
Thank you so much for helping me.

I’m glad that helped. Mark the post that helped as a solution to help others :slight_smile: