I created a small app to make notes and initial test of AI LLM POC.
Entire app works as intended except when editing notes. Always throws a dreaded “NoReverseMatch” (added word doc of the entire error).
NOTE: I deleted the all the *.html files and views.py functions, urls.py etc. and started all over again copy and pasting the code from another app I have written and used many times as a template. Basically only having to change the namespace, models info etc. Only this app (hyperapp) is having the issue.
The error is in edit_notes.html hx-post=“{% url ‘hyperapp:notes_submit’ item.pk %}”
----------------------- ADDING THE ERROR BCUZ CANNOT FIND ATTACH OPTION ---------------
NoReverseMatch at /hyperapp/edit_notes/55/
Reverse for ‘notes_submit’ with arguments ‘(’‘,)’ not found. 1 pattern(s) tried: [‘hyperapp/notes_submit/(?P[0-9]+)/\Z’]
Request Method: | GET |
---|---|
Request URL: | http://127.0.0.1:8000/hyperapp/edit_notes/55/ |
Django Version: | 5.0.6 |
Exception Type: | NoReverseMatch |
Exception Value: | Reverse for ‘notes_submit’ with arguments ‘(’‘,)’ not found. 1 pattern(s) tried: [‘hyperapp/notes_submit/(?P[0-9]+)/\Z’] |
Exception Location: | C:\Users\EAI24909\OneDrive - Epson America\Desktop\Python Projects\epson.epsonVE\Lib\site-packages\django\urls\resolvers.py, line 851, in _reverse_with_prefix |
Raised during: | hyperapp.views.edit_notes |
Python Executable: | C:\Users\EAI24909\OneDrive - Epson America\Desktop\Python Projects\epson.epsonVE\Scripts\python.exe |
Python Version: | 3.11.9 |
Python Path: | ['C:\Users\EAI24909\OneDrive - Epson America\Desktop\Python ’ ‘Projects\epson\.epsonVE\enoc_proj’, ‘C:\Program Files\Python311\python311.zip’, ‘C:\Program Files\Python311\DLLs’, ‘C:\Program Files\Python311\Lib’, ‘C:\Program Files\Python311’, 'C:\Users\EAI24909\OneDrive - Epson America\Desktop\Python ’ ‘Projects\epson\.epsonVE’, 'C:\Users\EAI24909\OneDrive - Epson America\Desktop\Python ’ ‘Projects\epson\.epsonVE\Lib\site-packages’, 'C:\Users\EAI24909\OneDrive - Epson America\Desktop\Python ’ ‘Projects\epson\.epsonVE\Lib\site-packages\odf’, 'C:\Users\EAI24909\OneDrive - Epson America\Desktop\Python ’ ‘Projects\epson\.epsonVE\Lib\site-packages\odf’, 'C:\Users\EAI24909\OneDrive - Epson America\Desktop\Python ’ ‘Projects\epson\.epsonVE\Lib\site-packages\odf’, 'C:\Users\EAI24909\OneDrive - Epson America\Desktop\Python ’ ‘Projects\epson\.epsonVE\Lib\site-packages\odf’, 'C:\Users\EAI24909\OneDrive - Epson America\Desktop\Python ’ ‘Projects\epson\.epsonVE\Lib\site-packages\odf’, 'C:\Users\EAI24909\OneDrive - Epson America\Desktop\Python ’ ‘Projects\epson\.epsonVE\Lib\site-packages\odf’, 'C:\Users\EAI24909\OneDrive - Epson America\Desktop\Python ’ ‘Projects\epson\.epsonVE\Lib\site-packages\odf’] |
Server time: | Sun, 21 Jul 2024 12:29:28 -0500 |
Error during template rendering
In template C:\Users\EAI24909\OneDrive - Epson America\Desktop\Python Projects\epson\.epsonVE\enoc_proj\hyperapp\templates\hyperapp\edit_notes.html
, error at line 13
Reverse for ‘notes_submit’ with arguments ‘(’‘,)’ not found. 1 pattern(s) tried: [‘hyperapp/notes_submit/(?P[0-9]+)/\Z’]
3 | {{ form.content.errors }} | |
---|---|---|
4 | ||
5 | {{ form.created_date }} | |
6 | {{ form.created_date.errors }} | |
7 | ||
8 | ||
9 | ||
10 | <button type=“button” | |
11 | class=“btn-sm btn-outline-success” | |
12 | hx-headers=‘{“X-CSRFToken”: “{{ csrf_token }}”}’ | |
13 | hx-post=“{% url ‘hyperapp:notes_submit’ item.pk %}” |
I will add the relevant code below for viewing.
urls.py
from django.urls import path, include
from django.contrib import admin
from django.contrib.auth import login, logout
from django.urls import reverse
from . import views
app_name = 'hyperapp'
urlpatterns = [
path("hyperapp/", views.hyperindex, name="hyperhome"),
path("add", views.add_notes_view, name="add_notes_view"),
]
htmxpatterns = [
path("delete/<int:pk>/", views.delete_notes_view, name="delete_notes"),
path('edit_notes/<int:pk>/', views.edit_notes, name='edit_notes'),
path('notes_submit/<int:pk>/', views.notes_submit, name='notes_submit'),
path('setOrderby/', views.setOrderby, name='setOrderby'),
path('search_results_view/', views.search_results_view, name='search_results_view'),
]
urlpatterns += htmxpatterns
models.py
from django.db import models
class NotesModel(models.Model):
content = models.CharField(max_length=1000,blank=True,null=True)
created_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.content
views.py
from .models import NotesModel
_ORDBY = ('-id') # setting default global var for order_by
_ITEMS_PER_PAGE = 4
def hyperindex(request):
notes = NotesModel.objects.all().order_by(_ORDBY) # new
paginator = Paginator(notes, _ITEMS_PER_PAGE)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
template = 'hyperapp/hyperindex.html'
return render(request, template, {'page_obj': page_obj, 'count': notes.count()})
@require_http_methods(["GET", "POST"])
def setOrderby(request):
template = 'hyperapp/lists.html'
global _ORDBY # get global var ready for change
if request.method == "POST":
if request.POST.get("wordup", None) is None:
_ORDBY = ('-id') # something happened with request so reset to (-id)
else:
inputtxt = request.POST.get('wordup')
if inputtxt == "order_by_content":
if _ORDBY == ('content'): # check to see if _ORDBY already equals 'title'
_ORDBY = ('-id') # change order by now
else:
_ORDBY = ('content')
else: # default _ORDBY = ('-id') if inputtxt had an issue
_ORDBY = ('-id')
notes = NotesModel.objects.all().order_by(_ORDBY) # NOTE: _ORDBY is a variable
paginator = Paginator(notes, _ITEMS_PER_PAGE)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(request, template, {'page_obj': page_obj, 'count': notes.count()})
@require_http_methods(["GET", "POST"])
def add_notes_view(request):
content = request.POST.get('note_content') # new
note = NotesModel.objects.create(content=content) # new
note.save() # new
notes = NotesModel.objects.all().order_by(_ORDBY) # new
paginator = Paginator(notes, _ITEMS_PER_PAGE) # new
page_number = request.GET.get('page') # new
page_obj = paginator.get_page(page_number) # new
template = 'hyperapp/lists.html' # new
return render(request, template, {'page_obj': page_obj, 'count': notes.count()}) # new
def delete_notes_view(request,pk):
note = NotesModel.objects.get(pk=pk) # changed from id=pk to pk=pk
note.delete()
notes = NotesModel.objects.all().order_by(_ORDBY)
paginator = Paginator(notes, _ITEMS_PER_PAGE)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
template = 'hyperapp/lists.html'
return render(request, template, {'page_obj': page_obj, 'count': notes.count()})
class NoteForm(forms.ModelForm):
class Meta:
model = NotesModel
exclude = []
@require_http_methods(["GET", "POST"])
def edit_notes(request, pk):
note = NotesModel.objects.get(pk=pk)
context = {}
context['note'] = note
print(pk)
context['form'] = NoteForm(initial={
'content': note.content,
'created_date' : note.created_date
})
print("JOHN", context)
template = 'hyperapp/edit_notes.html'
return render(request, template, context)
@require_http_methods(["GET", "POST"])
def notes_submit(request, pk): # changed edit_notes_submit to notes_submit
print("notes_submit")
context = {}
note = NotesModel.objects.get(pk=pk)
context['note'] = note
print("context jbh:", context)
if request.method == 'POST':
print("post")
form = NoteForm(request.POST, instance=note)
if form.is_valid():
form.save()
notes = NotesModel.objects.all().order_by(_ORDBY)
else:
template = 'hyperapp/edit_note.html'
return render(request, template, context)
template = 'hyperapp/note_row.html'
return render(request, template, context)
@require_http_methods(["GET", "POST"])
def search_results_view(request):
query = request.GET.get('search', '') # NOTE: ‘search’ is from the input control in search html file
note = NotesModel.objects.all()
if query:
#notes = note.filter(content__icontains=query) # NOTE: 'title' is field from models.py
notes = note.filter(content__startswith=query)
paginator = Paginator(notes, _ITEMS_PER_PAGE)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
else: # if we get here then there was no query match
notes = []
notes = NotesModel.objects.all().order_by(_ORDBY)
paginator = Paginator(notes, _ITEMS_PER_PAGE)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
template = 'hyperapp/lists.html'
return render(request, template, {'page_obj': page_obj, 'count': notes.count()})
context = {'page_obj': page_obj}
template = 'hyperapp/lists.html'
return render(request, template, context)
base.html
{% load static %}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}{% endblock %}</title>
<!-- Bootstrap 5 css -->
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
</head>
<body>
<div class="container mt-5">
{% block content %}
{% endblock %}
</div>
<script src="{% static 'js/bootstrap.bundle.min.js' %}"></script>
<script src="{% static 'js/htmx.min.js' %}"></script>
{% block js_script %}
{% endblock %}
<script>
document.body.addEventListener('htmx:configRequest', (event) => {
event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
})
</script>
</body>
</html>
hyperindex.html
{% extends 'hyperapp/base.html' %}
{# load static #}
{% block title %} Home {% endblock %}
{% block content %}
<h3 class="my-5">Notes</h3>
{% csrf_token %}
<!-- this section is for the search box -->
<input class="form-control" type="search"
name="search" placeholder="Begin Typing To Search for a title..."
hx-get="{% url 'hyperapp:search_results_view' %}"
hx-trigger="keyup changed delay:500ms"
hx-target="#notes_results">
<br>
<form hx-post="{% url 'hyperapp:add_notes_view' %}" hx-target="#notes_results" class="mx-auto" hx-on::after-request="this.reset()">
{% csrf_token %}
<div class="mb-3 row align-items-center">
<label for="noteText" class="col-auto col-form-label">Enter new notes here: </label>
<div class="col-6">
<input type="text" name="note_content" class="form-control" placeholder="Enter notes here">
</div>
<div class="col-auto">
<button class="btn-sm btn-outline-primary">Add Notes</button>
</div>
</div>
</form>
<div id="notes_results">
{% include 'hyperapp/lists.html' %}
</div>
<!-- chat col -->
<div class="col">
<div class="card">
<div class="card-header">
eAI Chat
</div>
<div class="card-body">
<div class="overflow-auto p-3 bg-light" style="width: 450px; height: 600px;">
<p id="results"></p>
</div>
</div>
<div class="card-footer text-body-secondary">
<form action="">
<input type="text" name="search_query" class="form-control" placeholder="Ask A question"
hx-post="{% url 'hyperapp:ask_llm' %}"
hx-target="#results"
hx-trigger="keyup changed delay:5s"
hx-swap="beforeend"
>
<br>
<button type="reset" class="btn btn-danger">Clear</button>
<button type="Submit" class="btn btn-primary"
hx-post="{% url 'hyperapp:ask_llm' %}"
hx-target="#results"
hx-swap="beforeend"
>Send</button>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js_script %}
<script>
document.body.addEventListener('htmx:configRequest', (event) => {
event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
})
</script>
{% endblock %}
lists.html
{% if page_obj %}
<!-- NOTE: this option on the next ** line overflow-y: auto; ** is what allows scrollable tables but when I
inserted the code for pagination this feature seems to disable itself. interesting-->
<div class="table-responsive" style="height: 500px; overflow-y: auto;">
<table class="table table-striped w-100 d-block d-md-table">
<form>
<thead>
<div>
<input type="hidden" id="txword" name="wordup" value="order_by_content">
<th>
<a class="" href=""
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-post="{% url 'hyperapp:setOrderby' %}"
hx-trigger="click"
hx-target="#notes_results"
hx-include="[name='wordup']"
>Content</a>
</th>
</div>
<th>Created</th>
</thead>
</form>
<tbody>
{# for item in notes #}
{% for item in page_obj %}
{% include 'hyperapp/note_row.html' %}
{% endfor %}
</tbody>
</table>
</div>
<div class="btn-group" role="group" aria-label="Item pagination">
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}" class="btn btn-outline-primary">«</a>
{% endif %}
{% for page_number in page_obj.paginator.page_range %}
{% if page_obj.number == page_number %}
<button class="btn btn-outline-primary active">
<span>{{ page_number }} <span class="sr-only">(current)</span></span>
</button>
{% else %}
<a href="?page={{ page_number }}" class="btn btn-outline-primary">
{{ page_number }}
</a>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}" class="btn btn-outline-primary">»</a>
{% endif %}
</div>
<div>Total record count: {{ count }}</div>
{% else %}
<h5>Currently, you don't have any notes. Or there were no search matches.</h5>
{% endif %}
note_row.html
<tr>
<td style="word-wrap: break-word;min-width: 60px;max-width: 60px;">{{ item.content }}</td>
<td style="word-wrap: break-word;min-width: 50px;max-width: 50px;">{{ item.created_date }}</td>
<td>
<button type="button"
class="btn-sm btn-outline-danger"
hx-get="{% url 'hyperapp:delete_notes' item.pk %}"
hx-target="#notes_results"
hx-confirm="Are you sure you wish to delete?"
style="cursor: pointer;">
DEL
</button>
<button type="button"
class="btn-sm btn-outline-warning"
hx-get="{% url 'hyperapp:edit_notes' item.pk %}"
hx-target="closest tr"
hx-swap="outerHTML"
style="cursor: pointer;">
Edit
</button>
</td>
</tr>
edit_notes.html
<tr>
<td style="word-wrap: break-word;min-width: 60px;max-width: 60px;">{{ form.content }}
{{ form.content.errors }}
</td>
<td>{{ form.created_date }}
{{ form.created_date.errors }}
</td>
<td>
<button type="button"
class="btn-sm btn-outline-success"
hx-post="{% url 'hyperapp:notes_submit' item.pk %}"
hx-target="closest tr"
hx-swap="outerHTML"
hx-include="closest tr" >
Save
</button>
<button type="button"
class="btn-sm btn-outline-dark"
hx-get="{% url 'hyperapp:notes_submit' item.pk %}"
hx-target="closest tr"
hx-swap="outerHTML">
Cancel
</button>
</td>
</tr>