Skip to content
Advertisement

how can i load objects filtered through a form in django?

i’m using django to store photos in a server. these photos are stored through a model that has an imageField and a charField called tags. i’m looking to filter objects from my database using keywords i receive from a form. the form is in a file called navbar.html:

 <form class="form-inline my-2 my-lg-0" action="{% url 'filtered' searched_tags %}" method="GET">

    <input class="form-control mr-sm-2" name="searched_tags" type="search" placeholder="Cerca" aria-label="Cerca">

    <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Cerca</button>

 </form>

i’ve defined a function in my views.py called filtered:

 def filtered(request, searched_tags):
    input_field = request.GET.get('searched_tags')
    print(input_field)
    filtered_photos = Photo.objects.filter(tags=input_field)
    context = {'photos': filtered_photos}

    return render(request, 'grid.html', context)

(also i’m not sure why but print doesn’t always work)

and finally urls.py:

urlpatterns = [
  path('', views.home, name="home"),
  path('lazy_load/', views.lazy_load, name="lazy_load"),
  path('addPhoto/', views.addPhoto, name="addPhoto"),
  path('<str:searched_tags>', views.filtered, name="filtered"),
] 

i get the error :

NoReverseMatch at / Reverse for ‘filtered’ with arguments ‘(”,)’ not found. 1 pattern(s) tried: [‘(?P<searched_tags>[^/]+)$’]

i’ve been looking for answers in here but i only found people using url in urls.py instead i’m using path. i also tried to understand reverse in the docs but i couldn’t understand especially because all the example are using url.


i know that this is not the best way to do this, i’ve seen people using filtering in different ways, but i think that for my needs this is the simplest way. thank you.

Advertisement

Answer

I believe you render this form on the view views.home. The problem is action="{% url 'filtered' searched_tags %}" does not make sense as likely there would be no context variable named searched_tags. Instead you should change your url patterns to have a fixed name (You get the search terms from the GET parameters anyway).

Your urlpatterns would be like

urlpatterns = [
    path('', views.home, name="home"),
    path('lazy_load/', views.lazy_load, name="lazy_load"),
    path('addPhoto/', views.addPhoto, name="addPhoto"),
    path('search/', views.filtered, name="filtered"),
]

Your view since it is now not passed any argument by the url:

def filtered(request):
    input_field = request.GET.get('searched_tags')
    print(input_field)
    filtered_photos = Photo.objects.filter(tags=input_field)
    context = {'photos': filtered_photos}

    return render(request, 'grid.html', context)

And your template would be:

<form class="form-inline my-2 my-lg-0" action="{% url 'filtered' %}" method="GET">
    <input class="form-control mr-sm-2" name="searched_tags" type="search" placeholder="Cerca" aria-label="Cerca">
    <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Cerca</button>
</form>
Advertisement