Reputation: 308
Hello Stackoverflow community,
I am having trouble with my form not rendering in Django.
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.
Upvotes: 1
Views: 1499
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
Reputation: 1707
I have noticed two particular problems in above screenshot. Firstly, my form does not render when inside my
index.html
webpage, which extendslayout.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