Alejandro Armas
Alejandro Armas

Reputation: 308

Implementing Search Form with Django

Hello Stackoverflow community,

I am having trouble with my form not rendering in Django.

Where the form is suppose to be

Here's my attempt to render an empty form in views.py.


class SearchSite(forms.Form):
    query = forms.CharField(label="New Item",
     help_text="Search for any article located on the site.")
    
def search(request):

    form = SearchSite()        
   
    context = {
        "form": form,
        "query_matches": query_matches
    }

    response = render(request, "encyclopedia/layout.html", context)
    return response

Here's what my urls.py file looks like:

urlpatterns = [
    path("", views.index, name="index"),
    path("wiki/<str:page_title>", views.page, name="wiki"),
    path("wiki/", views.search, name="site_search") 
]

My layout.html file:

{% load static %}

<!DOCTYPE html>

<html lang="en">
    <head>
        <title>{% block title %}{% endblock %}</title>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
        <link href="{% static 'encyclopedia/styles.css' %}" rel="stylesheet">
    </head>
    <body>
        <div class="row">
            <div class="sidebar col-lg-2 col-md-3">
                <h2>Wiki</h2>
                
                <form action="{% url 'site_search' %}" method="get">
                    {% csrf_token %}
                    There should be something here
                    {{ form }}
                    <input type="submit">
                </form>

                <div>
                    <a href="{% url 'index' %}">Home</a>
                </div>
                <div>
                    Create New Page
                </div>
                <div>
                    Random Page
                </div>
                {% block nav %}
                {% endblock %}
            </div>
            <div class="main col-lg-10 col-md-9">
                {% block body %}
                {% endblock %}
            </div>
        </div>

    </body>
</html>

I have noticed two particular problems in above screenshot. Firstly, my form does not render when inside my index.html webpage, which extends layout.html. Secondly, when I click the submit button, I get routed to a webpage that has my CSRF token in the url ... and then finally renders my form.

How can I fix this? Thanks everyone.

Where I get linked Instead

Upvotes: 1

Views: 1499

Answers (2)

Alejandro Armas
Alejandro Armas

Reputation: 308

Here's my solution to the problem I had earlier for any future people visiting the post.

I wrote a form called SearchSite and defined a view called search in my views.py.

class SearchSite(forms.Form):
    query = forms.CharField(
     help_text="Search for any article located on the site.")
    
def search(request):

    form = SearchSite()
    is_substring_of_queries = []
        
    if request.method == "GET":
        form = SearchSite(request.GET)
        
        if form.is_valid():
            for entry in util.list_entries():
                existsIdenticalResult = form.cleaned_data["query"].casefold() == entry.casefold() 
                existsResult = form.cleaned_data["query"].casefold() in entry.casefold()    
                if existsIdenticalResult:
                    return HttpResponseRedirect(reverse("wiki",
                     kwargs={"page_title": entry}))
                elif existsResult: 
                    is_substring_of_queries.append(entry)
        
    context = {
        "form": SearchSite(),
        "is_substring_of_queries": is_substring_of_queries
    }

    response = render(request, "encyclopedia/search.html", context)
    return response

When my view.search is requested, it will send the response of either an empty form (if accessed by index.html or if there are no results with a message saying there are no results) , an empty form and all the queries that are substrings of the markdown entries or route the client to an exact entry if the query matched.

Here's the routing down in my urls.py so far:

urlpatterns = [
    path("", views.index, name="index"),
    path("wiki/<str:page_title>", views.page, name="wiki"),
    path("search/", views.search, name="site_search")
]

In my layout.html, I have the following form:

<form action="{% url 'site_search' %}" method="get">
    {{ form }}                
    <input type="submit">
</form>

as well as in my search.html the queries that are substrings of the markdown entries:

{% if is_substring_of_queries %}
        <h1>Search Results</h1>
            {% for query in is_substring_of_queries%}
                <li><a href="{% url 'wiki' query %}"> {{ query }} </a></li>
                {% endfor %}
            {% else %}

        <h1>No Results! Try again.</h1>
        {% endif %}

If there are any mistakes, please let me know.

Upvotes: 1

Safwan Samsudeen
Safwan Samsudeen

Reputation: 1707

I have noticed two particular problems in above screenshot. Firstly, my form does not render when inside my index.html webpage, which extends layout.html.

Yes. You aren't passing form to index.html. Pass that in the view which renders the homepage. Even if it extends from layout.html, you need to pass it in the context for it to work.

def index(request):
    # Your code.
    return render(request, 'index.html', {'form': SearchSite()})

Secondly, when I click the submit button, I get routed to a webpage that has my CSRF token in the url ... and then finally renders my form.

That's because, in index.html, there is a blank form with a csrf_token, with an action set to /wiki, which calls search when the submit button is pressed. And search gives you layout.html, with the form, and as the form method is GET, it shows it in the url. I suggest changing it to POST if there is confidential data (and even otherwise. Why is there a csrf_token if it is not a POST request? Not needed. If you really want a GET request, then remove the csrf_token).

Upvotes: 1

Related Questions