I currently have a working search form in my project that passes through form data to the GET request. Pretty standard.
What I'm wanting to do is search as data is entered into the search form, so that results will display in real time with search data. This is much like what Google does with the instant desktop results. Is this something that's possible with Django?
Below is my current (simple) search
#views.py
def ProductView(request):
title = 'Products'
all_products = Product.objects.all().order_by("product_Name")
query = request.GET.get("q")
if query:
products = all_products.filter(
Q(product_Name__contains=query) |
Q(manufacturer__contains=query)
).distinct()
return render(request, 'mycollection/details.html', { 'all_products' : products })
-
<!-- HTML -->
<!-- SEARCH BAR -->
<form class="navbar-form navbar-left" role="search" method="get" action="{% url 'mycollection:products' %}">
<div class="form-group">
<input type="text" class="form-control" name="q" value="{{ request.GET.q }}">
</div>
<button type="submit" class="btn btn-default">Search</button>
</form>
you can save the request.data in to session and if any data is associated with session search data you can put in to value of search box.
request.session['search'] = request.GET.get('q','')
templete :
{% if request.session.search %} {{request.session.search}} {% endif %}
Related
As you can see in the picture below I'm trying to have the user search for a given country, start/end date and get the result of "Confirmed Cases" and "Date" back from the API, but I'm not sure how to do it.
I tried using this API, to fill the drop-down menu of the countries -->
https://api.covid19api.com/summary
but this is the other API that I have to use but while changing the parameters for the country and dates -->
https://api.covid19api.com/country/afghanistan/status/confirmed?from=2020-09-06T00:00:00Z&to=2020-09-11T00:00:00Z
Here are snippets of my code:
views.py
def home(request):
# second_response = requests.get('https://api.covid19api.com/country/afghanistan/status/confirmed?from=2020-09-06T00:00:00Z&to=2020-09-11T00:00:00Z').json()
second_response = requests.get('https://api.covid19api.com/summary').json()
my_list = []
for i in range(0, len(second_response['Countries'])):
my_list.append(second_response['Countries'][i]['Country'])
if request.method=='POST':
selected_country = request.POST['selected_country']
print('here', selected_country)
return render(request, 'home.html', {'my_list': my_list})
home.html
<div class="container justify-content-center">
<form action="{% url 'home' %}" method="post">
{% csrf_token %}
<label for="selected_country" style="margin-right: 5px;"> Select a Country, Start & End Dates : </label>
<select name="selected_country" >
{% for object in my_list %}
<option value="">{{object}}</option>
{% endfor %}
</select>
<label for="startdate"></label>
<input type="date" id="startdate">
<label for="enddate"></label>
<input type="date" id="enddate">
<input type="submit" value="Search" />
</form>
</div>
PLUS: when I click on "search" i should get the value of the selected_country because I tried printing it, but it doesn't show for some reason, so the method is post but for some reason I can't get back the selected_country
Any help is appreciated
JAVASCRIPT
if you have any solid grasp of javascript i recommend you do that in javascript, because it will just make it better and easier
otherwise :
view.py
def handler(request):
if request.method=='POST':
selected_country = request.POST['selected_country']
startDate= request.POST['startdate']
endDate= request.POST['enddate']
request_handler = requests.get(f"https://api.covid19api.com/country/{selected_country}/status/confirmed?from={startDate}T00:00:00Z&to={endDate}T00:00:00Z")
if request_handler.status_code=200:
#To prevent errors
request_json=request_handler.json()
else:
pass # do something
return render(request, 'result.html', {"json":request_json})
#you should handle the data at the front end using jinja blocks
note : i don't know much about Django so the code may break
I am trying to create a function to search for objects in base.html from the database using a keyword and printing the results in listing.html
base.html
<form method="post" action="{% url 'listing'}" name="searchform">
{% csrf_token %}
<div class="custom-form">
<label>Keywords </label>
<input type="text" placeholder="Property Keywords" name="search_keyword" value=""/>
<label >Categories</label>
<select data-placeholder="Categories" name = "home_type" class="chosen-select on-radius no-search-select" >
<option>All Categories</option>
<option>Single-family</option>
<option>Semi-detached</option>
<option>Apartment</option>
<option>Townhomes</option>
<option>Multi-family</option>
<option>Mobile/Manufactured</option>
<option>Condo</option>
</select>
<label style="margin-top:10px;" >Price Range</label>
<div class="price-rage-item fl-wrap">
<input type="text" class="price-range" data-min="10000" data-max="100000000000" name="price-range1" data-step="1" value="1" data-prefix="$₦">
</div>
<button onclick="location.href='listing'" type="button" class="btn float-btn color-bg"><i class="fal fa-search"></i> Search</button>
</div>
</form>
views.py
def listing(request):
global search_keyword
p = Paginator(Property.objects.order_by('-listed_on'), 2)
page = request.GET.get('page')
propertys = p.get_page(page)
nums = "p" * propertys.paginator.num_pages
if request.method == 'POST' and 'searchform' in request.POST :
search_keyword = request.POST['search_keyword']
propertys = Property.objects.filter(name__contains=search_keyword)
return render(request, 'listing.html',{'nums':nums, 'search_keyword':search_keyword, 'propertys':propertys})
return render(request, 'listing.html',{'nums':nums,'propertys':propertys})
Your syntax of url[django-doc] tag is wrong, it must be {% url 'listing' %} not {% url 'listing'}, you forget to add % at the end which is not the syntax of django template language.
Try this:
Template file:
<form method="POST" action="{% url 'listing' %}" name="searchform">
You can also make use of __icontains for case-insensitive.
i want to display my django search result on a new html page instead of the page where the search bar is. i have tried manipulating my form tag and it still does'nt redirect to the page when i search, rather it stays on the same page.
index.html
<form action="{% url 'elements:all-elements' %}" method="get">
<input type="text" class="form-control" name="q" value="{{ request.GET.q }}" type="text" placeholder="Search Free Web Elements and Resources">
<button type="submit" class="btn bt-round" ><b><i class="bi bi-search"></i></b></button>
</form>
views.py - this is the view handling the seach, i dont know if anything would be appended there
# Search Function
query = request.GET.get("q")
if query:
vectors = vectors.filter(
Q(title__icontains=query)).distinct()
You can render new template for your search results.
def search(request):
query = request.GET.get("q")
vectors = Model.objects.all()
if query:
vectors = vectors.filter(
Q(title__icontains=query)).distinct()
context = {"vectors":vectors}
return render(request, "template", context)
So, Im trying to save a todo to a database with django. My template is as follows:
<form action="{% url 'todo:add' %}" method="POST">
{% csrf_token %}
<input type="text" id="text" value="{{new_todo_text}}"/>
<input type="submit" value="Submit todo" />
</form>
{%if not_done_todos %}
<ul>
{%for todo in not_done_todos%}
<li>
<span>{{todo.text}}</span>
</li>
{%endfor%}
</ul>
{%else%}
<span>No todos for you!</span>
{%endif%}
My view where Im trying to catch the "new_todo_text" looks like this:
def add(request):
"""Add todo to database"""
new_todo = Todo(text=request.POST.get('new_todo_text'),
done=False, date_created=timezone.now())
new_todo.save()
return HttpResponseRedirect(reverse('todo:index'))
The problem is that the todo.text turns up empty no matter what I add to the form... whats my problem here?
The problem is that inside your input element you have not declared a name attribute. That name attibute will be used as a key to fetch it with Django request.POST.
So, change to this:
<input type="text" id="text" name="new_todo_text" value="{{new_todo_text}}"/>
The request.POST dict-like will use the input's name and value to build the dict. Then you can do stuff like request.POST['input_name_here'].
I am able to add a new entry to my database using WTForms and Flask and I can edit too, the problem is that I need to display the already existing information in the database in an edit form.
I have the following code:
A Class For the Edit Post Form
class editPostForm(Form):
postTitle = TextField('postTitle', validators.Required()])
postSubtitle = TextField('postSubtitle', validators.Required()])
A Route for the Edit Post Template
#app.route('/editpost/<postId>', methods = ['GET','POST'])
def editpost_page(postId):
try:
form = editPostForm(form)
if request.method == "POST" and form.validate():
postTitle = form.postTitle.data
postSubtitle = form.postSubtitle.data
c, conn = connection()
query = c.execute("SELECT * FROM posts WHERE post_id = (%s)",
[noinjection(postId)])
c.execute("UPDATE posts SET post_title=%s, post_subtitle=%s WHERE post_id = %s",
[
noinjection(postTitle),
noinjection(postSubtitle),
noinjection(postId)
])
conn.commit()
flash("Post Edited", 'success')
c.close()
conn.close()
gc.collect()
return redirect(url_for('posts'))
return render_template("editpost.html", form = form, POST_ID = postId)
except Exception as e:
return(str(e))
The Edit Post Template {jinja}
{% extends "header.html" %}
{% block body %}
<body>
<div class="container-fluid">
<br />
<h4>Edit Post</h4>
<br />
{% from "_formhelpers.html" import render_field %}
<form action="/editpost/{{ POST_ID }}" class="form-horizontal" method="post">
{% from "_formhelpers.html" import render_field %}
<form action="/editpost/" method="post">
<div class="form-group">
<label for="postTitle">Post Title</label>
<input type="text" class="form-control" id="postTitle" name="postTitle" placeholder="Post Title" value="{{request.form.postTitle}}">
</div>
<div class="form-group">
<label for="postSubtitle">Post Subtitle</label>
<input type="text" class="form-control" id="postSubtitle" name="postSubtitle" placeholder="Post Subtitle" value="{{request.form.postSubtitle}}">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
{% if error %}
<p class="error"><strong>Error: </strong>{{error}}</p>
{% endif %}
</form>
{% if error %}
<p class="error"><strong>Error: </strong>{{error}}</p>
{% endif %}
</div>
</body>
{% endblock %}
With the following code, I am getting a selected post to update in the database, but the editpost template is not showing the values which are already in the database and all the fields are blank.
How can I pre-populate the form before editing?
You can populate each field separately like this:
form = editPostForm(form)
form.postTitle.data = postTitle_from_database
form.postSubtitle.data = postSubtitle_from_database
or you can populate your form fields from a given object using process method:
process(formdata=None, obj=None, **kwargs)
Take form, object data, and keyword arg input and have the fields
process them.
Parameters:
formdata – Used to pass data coming from the enduser, usually request.POST or equivalent.
obj – If formdata has no data for a field, the form will try to get it from the passed object.
**kwargs – If neither formdata or obj contains a value for a field, the form will assign the value of a matching keyword argument
to the field, if provided.
Since BaseForm does not take its data at instantiation, you must call
this to provide form data to the enclosed fields. Accessing the
field’s data before calling process is not recommended.
I was able to pre-populate HTML input and textarea fields from a SQL database with Python and Jinja as follows:
1. Store relevant data from database in a variable:
name = db.execute("""SELECT name FROM users WHERE id = :id""", id=session["user_id"])
about = db.execute("""SELECT about FROM users WHERE id = :id""", id=session["user_id"])
2. Render template (with render_template function) and pass in the relevant variables:
return render_template("edit.html", name = name, about = about)
3. Pass variables via jinja to html input and textarea elements. Index into the object that has been passed as follows:
For an input tag use the value attribute as below:
<input type="text" class="form-control" name="name" value="{{ name[0]["name"] }}">
For a textarea element:
<textarea class="form-control" name="about">{{ about[0]["about"] }}</textarea>