1

I am trying to create a simple search form(search by zip code), but am struggling to pass the user's input to a view:

 <form action="{% url 'search_results' query %}" method="post">
   <div>
     {% csrf_token %}
     <input type = 'text' name = 'query' placeholder="Zip Code" />
     <button type="submit" name="button">Find Jobs</button>
   </div>
 </form>

urls.py:

path('search_results/<str:query>', job_views.search_results, name = 'search_results'),

views.py:

def search_results(request, query):
    query = request.GET['query']
    return HttpResponse(query) # just trying to see if this view has access to 'query'

I'm not sure what is going on here. This returns

raise NoReverseMatch(msg)
django.urls.exceptions.NoReverseMatch: Reverse for 'search_results' with a
rguments '('',)' not found. 1 pattern(s) tried: ['search_results\\/(?P<que
ry>[^/]+)$']

Thanks for any help!

Justin
  • 1,029
  • 2
  • 10
  • 17

2 Answers2

1

In your form, at the line: action="{% url 'search_results' query %}", you are trying to pass query to the url tag, which would be fine if query had a value, but in your case query isn't defined.

Instead, you're form should look like this:

<form action="{% url 'search_results' %}" method="GET">
   <div>
     <input type = "text" name = "zip_code" placeholder="Zip Code" />
     <button type="submit" name="button">Find Jobs</button>
   </div>
</form>

Notice that I removed query from your url tag, and changed the method to GET, see this question for details.

Now change your path:

path('search_results', job_views.search_results, name = 'search_results')

You don't need to add query to the path, because Django will do it for you in your view:

def search_results(request):
    zip_code = request.GET.get('zip_code')
    print(zip_code)
    ...
Lord Elrond
  • 9,016
  • 3
  • 20
  • 50
  • 1
    Second time you've answered one of my questions, thanks. Also, great question about POST vs GET. – Justin Jan 25 '20 at 17:42
0

That's not how templates work.

Templates are used to produce a response, which gets returned to the requester. In this case, your main view produces an HTML document which will be passed to a browser. That document contains results of the url template tag, which is determined before the user even sees it. Template tags are not a way to refer to the state of DOM objects!

Instead, you should usually have a view with a stable URL, not varying with the query. Typically you'll then extract the query text from the form data representation - here, it'd be the request.POST dictionary-like object or (usually better) a Django form that you bind to the POST data, because your form uses method="post".

It would be possible to use Javascript to edit the DOM and change your form action prior to submitting it to include the query text, but that's not the usual pattern for working with forms. And template tags will never do that - they're only used to generate the response.

Peter DeGlopper
  • 32,557
  • 6
  • 77
  • 74