PHACDataHub / django-htmx-autocomplete

A Django autocomplete component powered by htmx
MIT License
50 stars 4 forks source link

NoReverseMatch when using app namespace app_name='foo' #61

Open rdelazzeri opened 1 day ago

rdelazzeri commented 1 day ago

Hi,

I'm having trouble implementing autocomplete in my project. When I added app_name='foo' to urls.py, the autocomplete stopped working and the error message displayed was NoReverseMatch for 'autocomplete_name'. Did I miss something?

juleskuehn commented 1 day ago

You should not have an app_name defined in your root urls.py, i.e. in settings.py: ROOT_URLCONF = "my_project.urls"

So in my_project/urls.py you might have:

# project urls
from django.urls import include, path
from autocomplete import HTMXAutoComplete

urlpatterns = [
    path('', include('foo.urls')),
    *HTMXAutoComplete.url_dispatcher("ac"),
]

And in foo/urls.py you can have the app_name defined:

# foo.urls
from django.urls import path

from . import views

app_name = 'foo'
urlpatterns = [
    path('', views.index(), name='index'),
]

See https://stackoverflow.com/questions/61254816/what-is-the-purpose-of-app-name-in-urls-py-in-django

rdelazzeri commented 21 hours ago

I changed the code and now the error is different:

FieldError at /
Cannot resolve keyword 'value' into field. Choices are: id, name, team

I made the same project structure on another machine and it is working there. But in this test project and the official project that I'm working on it's not working I don't know what could be wrong. The structure of the code is as follows:

#proj/settings.py
INSTALLED_APPS = [
    ...
    "django.contrib.staticfiles",
    'autocomplete',
    'app1'
]
#project/urls.py
from django.contrib import admin
from django.urls import path, include
from autocomplete import HTMXAutoComplete

urlpatterns = [
    *HTMXAutoComplete.url_dispatcher('ac'),
    path("admin/", admin.site.urls),
    path("", include('app1.urls')),

]
#proj/app1/urls.py
from django.urls import path, include
from . import views
from autocomplete import HTMXAutoComplete

app_name = 'app1'
urlpatterns = [
    path("", views.index, name='index'),
]
#proj/app1/views.py
from django.shortcuts import HttpResponse
from .models import *
from .forms import *
from django.template import loader

def index(request):
    template = loader.get_template("app1/index.html")
    my_form = MyForm()
    return HttpResponse(template.render({"form": my_form}, request,))
#proj/app1/forms.py
class MyForm(forms.ModelForm):
    class Meta:
        model = Team
        fields = ["name", "members"]
        field_classes = {"members": forms.ModelChoiceField}
        widgets = {
            "members": widgets.Autocomplete(
                name="members", options=dict(model=Person, minimum_search_length=0)
            )
        }
#proj/app1/models.py
from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=60)

class Team(models.Model):
    name = models.CharField(max_length=60)
    members = models.ManyToManyField(Person)
#proj/app1/templates/app1/index.html
{% load autocomplete %}
{% load static %}
<!doctype html>
<html lang="en">
  <head>
    <!-- Bootstrap -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
  </head>
  <body>
    <h1>Example base html template</h1>
      {{ form.as_table }}

    <!-- Bootstrap -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
    <!-- htmx -->
    <script src="https://unpkg.com/htmx.org@1.8.3" integrity="sha384-e2no7T1BxIs3ngCTptBu4TjvRWF4bBjFW0pt7TpxOEkRJuvrjRt29znnYuoLTz9S" crossorigin="anonymous"></script>
    <!-- htmx csrf -->
    <script>
      document.body.addEventListener('htmx:configRequest', (event) => {
        event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
      });
    </script>
  </body>
</html>