Django Search bar feature not working? - python

In my base template I have this search bar. When I search for something it doesn't actually return anything. I'm not sure if the url is correct because I want it to work on every page.
In the base navbar this is the code:
<form class="navbar-form navbar-left" target="_self">
<div class="form-group">
<label class="control-label" for="search-field">
<i class="glyphicon glyphicon-search"></i></label>
<input type="text/submit" value="{{request.GET.q}}" name="q"
class="form-control search-field"
action={% url 'search_posts' %}
placeholder="Search Airline or Aircraft" id="search-field" />
</div>
</form>
Urls.py
url(r'^$', search_posts, name='search_posts'),
Views.py
def search_posts(request):
aircraft = Aircraft.objects.all()
airline = Airline.objects.all()
query = request.GET.get("q")
if query:
aircraft = aircraft.filter(
Q(name__icontains=query) |
Q(description__icontains=query)
).distinct()
return render(request, 'search_post.html', {'aircraft': aircraft})
Is it possible to combine two models into a variable? I have Aircraft and Airline. Will this work?
queryset_list = Aircraft.objects.all() + Airline.objects.all()
Views.py Updated
def search_posts(request):
aircraft = Aircraft.objects.all()
airline = Airline.objects.all()
query = request.GET.get("q")
aircraft = aircraft.filter(
Q(name__icontains=query) |
Q(description__icontains=query)).distinct()
airline = airline.filter(
Q(name__icontains=query) |
Q(description__icontains=query)).distinct()
return render(request, 'search_post.html', {'aircraft': aircraft,'airline': airline })
search_post.html
<div class="team-boxed">
<div class="container">
<div class="row aircraft">
{% for aircraft in aircraft %}
<div class="col-lg-offset-0 col-md-4 col-sm-3 item">
<div class="box"><img src="{{ aircraft.image.url }}" />
<h3 class="name">{{ aircraft.name }}</h3>
<h4><em>Range: {{ aircraft.maximum_range }} NM</em></h4>
<h4><em> Passengers: {{ aircraft.passengers }}</em></h4>
<h4><em> Speed: {{ aircraft.cruising_speed }} Kt</em></h4>
</div>
</div>
{% endfor %}
</div>
</div>
</div>

Since HTML input elements do not have an action attribute, remove action={% url 'search_posts' %} from <input> and place it inside the <form> like this:
<form action={% url 'search_posts' %} method="GET" ...>
Also remove the type="text/submit" from the input and replace it with just text (in order to present the user a text input box to write the query - thanks Alasdair for that - haven't seen that), like this:
<input type="text" ...>
so, the form should look like this:
<form method="GET" action={% url 'search_posts' %} class="navbar-form navbar-left">
<div class="form-group">
<label class="control-label" for="search-field">
<i class="glyphicon glyphicon-search"></i></label>
<input type="text" value="{{request.GET.q}}" name="q" class="form-control search-field" placeholder="Search Airline or Aircraft" id="search-field" />
</div>
</form>
Concerning the other part of your question, in order to combine two (or more) QuerySets (I can't imagine why you would want to do that), here it is:
qs = list(Aircraft.objects.all()) + list(Airline.objects.all())
Finally in your search_post.html do this:
{% if aircraft.exists %}
<div class="team-boxed">
<div class="container">
<div class="row aircraft">
{% for aircraft in aircraft %}
<div class="col-lg-offset-0 col-md-4 col-sm-3 item">
<div class="box"><img src="{{ aircraft.image.url }}"></div>
<h3 class="name">{{ aircraft.name }}</h3>
<h4><em>Range: {{ aircraft.maximum_range }} NM</em></h4>
<h4><em> Passengers: {{ aircraft.passengers }}</em></h4>
<h4><em> Speed: {{ aircraft.cruising_speed }} Kt</em></h4>
</div>
{% endfor %}
</div>
</div>
</div>
{% endif %}
{% if airline.exists %}
<div class="team-boxed">
<div class="container">
<div class="row airline">
{% for airline in airline %}
<div class="col-lg-offset-0 col-md-4 col-sm-3 item">
<div class="box"><img src="{{ airline.image.url }}"></div>
<h3 class="name">{{ airline.name }}</h3>
<h4><em>Range: {{ airline.maximum_range }} NM</em></h4>
<h4><em> Passengers: {{ airline.passengers }}</em></h4>
<h4><em> Speed: {{ airline.cruising_speed }} Kt</em></h4>
</div>
{% endfor %}
</div>
</div>
</div>
{% endif %}

Related

Flask apply filter with multiple checkboxes

Hey good people of stackoverflow,
My application randomly selects a recipe from MongoDB (using pymongo) and displays it to the user.
My intention is to be able to apply filters (vegetarian, fish, beef and so on) to the next "random" selection after hitting Something else button.
I think I can achieve it by using request.form.getlist and creating the form in the pick_meal.html but it feels a bit overkill.
So far I am unable to figure it out.
Any help would be greatly appreciated.
The html and python function looks like this:
{% extends 'base.html' %}
{% block content %}
<div class="container">
<h3>{% block title %} You should cook: {% endblock %}</h3>
<div class="row">
<div class="col-md-5 align-self-center text-center">
<span>{{ dish.dish_name }}</span>
</br>
</br>
<a class="btn btn-outline-success" href="{{ dish['dish_source'] }}" role="button">Go to web</a>
</div>
<div class="col-md-4">
<img src="{{ dish.dish_image }}" width="250px">
</div>
</div>
</br>
<div class="row">
<div class="col-md-5">
<button class="btn btn-primary">Something else</button>
<button class="btn btn-primary">Configrm choice</button>
<button class="btn btn-primary">Already cooked</button>
</div>
<div class="col-md-5">
<div class="form-check">
<input class="form-check-input" type="checkbox" value="vegetarian" id="flexCheckDefault" name="property_checkbox">
<label class="form-check-label" for="flexCheckDefault">Vegetarian</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="grill" id="flexCheckDefault" name="property_checkbox">
<label class="form-check-label" for="flexCheckDefault">Grill</label>
</div>
</div>
</div>
</div>
{% endblock %}
#app.route('/pick_meal/<string:dish_type>')
def pick_meal(dish_type):
# pick random meal based on category
dish = list(coll.aggregate([
{'$match':{
'cooked': False,
'dish_type': dish_type}},
{ '$sample':{
'size': 1 } }]))[0]
return render_template('pick_meal.html', dish=dish, dish_type=dish_type)

How to scroll lock a Django HTML Web Page

I am currently using a page that has a list of in-line forms
However when the user enters submits each form (line) they are sent back to the top of the page. This becomes really tedious as the users need to enter data quickly and can't when they need to scroll for 2 minutes every time they add an entry.
Does anyone know how to implement a scroll lock to stock this from happening
Views.py: Function:
class AvonleaView( View):
def get(self,request):
created_nums= AvonleaClass.objects.all().values('unitNumber')
Aprev = AvonleaClass.objects.all().order_by('-unitDateEntered')
# created_nums= AvonleaClass.objects.all()
print(created_nums )
created_nums =[int(i['unitNumber']) for i in created_nums]
print(created_nums )
form = AvonleaForm()
return render(request,"meter_readings/avonlea.html",{'form':form , 'created_nums':created_nums })
def post(self,request):
created_nums= AvonleaClass.objects.all().values_list('unitNumber')
print(created_nums)
form = AvonleaForm(request.POST)
if form.is_valid():
form.save()
return redirect('Avonlea')
messages.success(request , 'creates successfully ')
else:
return render(request, 'meter_readings/avonlea.html', {'form': form , created_nums:created_nums })
HTML page :
{% extends 'meter_readings/base.html' %}
{% block content %}
<!-- CSS only -->
<div class="container" font-size= 8px>
<center><h1>Avonlea Meter Readings</h1></center>
<br>
<head>
<meta name="viewport" content="width=device-width">
</head>
{% for unit_number in form.unitNumber %}
<h6>{{ error }}</h6>
<form class="form-group mt-4" method="post" {% if unit_number.data.value in created_nums %} style="background-color: rgb(231, 224, 224); " {% endif %} >
{% csrf_token %}
<div class="container">
<div class="row mb-3">
<div class="col">
<h5 style="font-size: 14px"> Unit number </h5>
{{ unit_number.data.value}}
</div>
<input type="hidden" name="unitNumber" value="{{unit_number.data.value}}">
<div class="col" id="prev{{unit_number.data.value}}" >
<h5 style="font-size: 14px"> Previous Reading </h5>
{{ previousReading }}
</div>
<div class="col" id="readings{{unit_number.data.value}}">
<h5 style="font-size: 14px"> Current Reading </h5>
{{ form.newReading }}
</div>
<div class="col" id="difference{{unit_number.data.value}}">
<h5 style="font-size: 14px"> Units Used </h5>
{{ form.difference }}
</div>
<div class="col" id="img{{unit_number.data.value}}">
{{ form.image }}
</div>
<div class="col">
<button id="form.id" class="btn btn-success " type="submit" {% if unit_number.data.value in created_nums %} disabled {% endif %} > Save</button>
</div>
</div>
</div>
</form>
{% endfor %}
<br>
<br>
If I understand correctly, you can add #<some_id> to the action attribute of your forms and when the page loads the browser will automatically put the element with the id="some_id" in view.
Example:
<form id="form1" action="#form2" method='POST'>...</form>
...
<form id="form2" action="" method='POST'>...</form>
If you submit #form1 when the page reloads the browser will scroll to #form2 even if it's at the bottom of the page.
Or if you only have one form, you can do:
<form id="form1" action="#form1" method='POST'>...</form>
EDIT:
<form id="form{{forloop.counter0}}" action="#form{{forloop.counter}}" class="form-group mt-4" method="post" {% if unit_number.data.value in created_nums %} style="background-color: rgb(231, 224, 224); " {% endif %} >

Search (โ€œ/searchโ€) app route in Flask not working- CS50 final project

I am currently working on my cs50 final project. I used the shows search function from week 9 source code as a reference to create my own search function. The search function is called using a form in the navigation bar in layout.html. The search function is not giving any error message in the terminal rather, it is showing the error page on the web application, everything seems fine on the terminal. The search function is similar to the index function and the index function works. I checked the sql query and it gives the appropriate results. Can someone identify the error in the code?
Reference:
https://cdn.cs50.net/2020/fall/lectures/9/src9.pdf- shows0/application.py
application.py
app = Flask(__name__)
#app.errorhandler(Exception)
def handle_exc(e):
if not isinstance(e, HTTPException):
e = InternalServerError()
return render_template("error.html", message=e.name, code=e.code)
db = SQL("sqlite:///ideahub.db")
#app.route("/")
def index():
ideas = db.execute("SELECT ideas.id AS id, username, user_id, idea_name, idea_body, post_date FROM ideas INNER JOIN users ON users.id = ideas.user_id WHERE posted = 1 ORDER BY post_date DESC")
for idea in ideas:
if idea["id"] in [row["idea_id"] for row in db.execute("SELECT idea_id FROM likes WHERE user_id = ?", session.get("user_id", 0))]:
idea["liked"] = True
return render_template("index.html", ideas=ideas)
#app.route("/search")
def search():
query = request.args.get("q")
ideas = db.execute("SELECT ideas.id AS id, username, user_id, idea_name, idea_body, post_date FROM ideas INNER JOIN users ON users.id = ideas.user_id WHERE posted = 1 AND idea_name LIKE '%?%' ORDER BY post_date DESC", query)
for idea in ideas:
if idea["id"] in [row["idea_id"] for row in db.execute("SELECT idea_id FROM likes WHERE user_id = ?", session.get("user_id", 0))]:
idea["liked"] = True
return render_template("search.html", ideas=ideas)
search.html
{% extends "layout.html" %}
{% block title %}
Search Results
{% endblock %}
{% block main %}
{% for i in range(ideas|length) %}
<div class="card bg-white col-10 mx-auto mb-2">
<div class="card-body">
<h5 class="card-title font-weight-bold" role="button" data-toggle="collapse" data-target="#idea-content-{{ i }}" aria-expanded="false">
{{ ideas[i].idea_name }} <i class="fas fa-angle-down fa-lg float-right"></i>
</h5>
<div class="collapse" id="idea-content-{{ i }}">
<p class="fw-600 card-text mb-2">Posted:- {{ ideas[i].post_date|date_format }}</p>
<p class="fw-600 card-text mb-2">Created By:- <a class="text-dark hover-link" href="/profile/{{ ideas[i].user_id }}">{{ ideas[i].username }}</a></p>
<p class="card-text">{{ ideas[i].idea_body }}</p>
{% if session.user_id != ideas[i].user_id %}
<form action="/like">
{% if ideas[i].liked %}
<button class="btn btn-primary mr-2" disabled>Liked!</button>
{% else %}
<button type="submit" class="btn btn-primary mr-2" name="id" value="{{ ideas[i].id }}">Like ๐Ÿ’›</button>
{% endif %}
</form>
{% endif %}
</div>
</div>
</div>
{% endfor %}
{% endblock %}
layout.html
<ul class="navbar-nav ml-auto mt-2">
<li class="nav-item">
<form class="search-bar bg-dark p-2 mr-2 d-flex justify-content-center align-items-center" action="/search">
<input class="search-input text-white border-0 bg-transparent" autocomplete="off" type="search" name="q" placeholder="Search...">
<button class="text-white deco-none float-right border-0 bg-transparent" type="submit"><i class="fas fa-search"></i></button>
</form>
</li>
</ul>
index.html
{% extends "layout.html" %}
{% block title %}
Homepage
{% endblock %}
{% block main %}
<h3 class="text-white offset-1 mb-3">Homepage</h3>
{% for i in range(ideas|length) %}
<div class="card bg-white col-10 mx-auto mb-2">
<div class="card-body">
<h5 class="card-title font-weight-bold" role="button" data-toggle="collapse" data-target="#idea-content-{{ i }}" aria-expanded="false">
{{ ideas[i].idea_name }} <i class="fas fa-angle-down fa-lg float-right"></i>
</h5>
<div class="collapse" id="idea-content-{{ i }}">
<p class="fw-600 card-text mb-2">Posted:- {{ ideas[i].post_date|date_format }}</p>
<p class="fw-600 card-text mb-2">Created By:- <a class="text-dark hover-link" href="/profile/{{ ideas[i].user_id }}">{{ ideas[i].username }}</a></p>
<p class="card-text">{{ ideas[i].idea_body }}</p>
{% if session.user_id != ideas[i].user_id %}
<form action="/like">
{% if ideas[i].liked %}
<button class="btn btn-primary mr-2" disabled>Liked!</button>
{% else %}
<button type="submit" class="btn btn-primary mr-2" name="id" value="{{ ideas[i].id }}">Like ๐Ÿ’›</button>
{% endif %}
</form>
{% endif %}
</div>
</div>
</div>
{% endfor %}
{% endblock %}
This sql gives an error to the effect that there are more parameters than placeholders:
SELECT ideas.id AS id, username, user_id, idea_name, idea_body, post_date
FROM ideas
INNER JOIN users ON users.id = ideas.user_id
WHERE posted = 1 AND idea_name LIKE '%?%'
ORDER BY post_date DESC
This %?% is a string literal. Either break the ? out from quotes or use named parameter (which would also not be in quotes). I don't know why you don't see this error in the flask log. That's ostensibly how I found it on repro.

send two forms with only one button in flask

I'm making a basic chat app with flask.
I have this page and this piece of code
#app.route('/', methods = ['GET', 'POST'])
def chat():
if request.method == 'POST':
message_content = request.form['content']
message_author = request.form['name']
if message_content:
new_message = Message(content = message_content, author = message_author)
db.session.add(new_message)
db.session.commit()
return redirect('/')
else:
all_messages = Message.query.order_by(Message.date.desc()).all()
return render_template('chat.html', posts=all_messages)
and I would like to every time I hit the "Send" button it takes the information of the input in the header and the info of the message. So, my question is, can I take the informations of two different forms with only one button ?
Html code (with a bit of jinja 2):
{% block body %}
<!-- Navbar -->
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="/">Chat</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav me-auto mb-2 mb-md-0">
</ul>
<form action="/" class="d-flex" method="POST">
FORM THAT CONTAINS THE NAME -- > <input class="form-control me-2" type="search" id="name" placeholder="Name" value="{% if message_author %}{{ message_author }}{% else %}Unknown{% endif %}" aria-label="Search">
<!-- <button class="btn btn-outline-success" type="submit">Save</button> -->
</form>
</div>
</div>
</nav>
<!-- New message form -->
<br>
<div class="bg-light p-5 rounded">
<h2 class="createPost">New message </h2>
<form action="/" method="POST">
<input type="text" name="content" id="content" class="createPost">
<br>
<input type="submit" value="Send" class="btn btn-outline-dark" id="submit">
</form>
</div>
<hr>
<!-- Display messages -->
{% for post in posts %}
<div class="">
{% if post.author %}
{% if post.date %}
<small class="">{{ post.date.replace(microsecond=0) }} - {{ post.author }} : </small>
{% else %}
<small class="">{{ post.author }}</small>
{% endif %}
{% else %}
{% if post.date %}
<small class="">{{ post.date }} - Unkown : </small>
{% else %}
<small class="">N/A - Unkown</small>
{% endif %}
{% endif %}
<p class="">{{ post.content }}</p>
Delete
<!-- Edit -->
<hr>
</div>
{% endfor %}
{% endblock %}
You could create a hidden input inside your send form and on submit copy the value (with javascript) of the input from the other form.
<input id="name" type="text" value="" name="name" class="btn btn-outline-dark" id="submit">
<form>
<input id="hiddenName" type="hidden" value="" name="name" class="btn btn-outline-dark" >
<input onclick="document.getElementById('hiddenName').value = document.getElementById('name').value" type="button" value="Send" class="btn btn-outline-dark" id="submit">
</form>

request.GET in Django for Search is not working when entering only one search parameters

This is my Search function:
When I use this than I cannot search by only placing for example Keywords only or City only or any other parameters that I have used here.
It comes with no Listing Available.
But if I remove any search parameters any only work with one parameter like:
if I remove all others except #Keywords than my search works out.
# search function using request.GET
def search(request):
# for making search option dynamic as per search of user
queryset_list = Listing.objects.order_by('-list_date')
#Keywords
if 'keywords' in request.GET:
keywords = request.GET['keywords']
if 'keywords':
queryset_list = queryset_list.filter(description__icontains=keywords)
#City
if 'city' in request.GET:
city = request.GET['city']
if 'city':
queryset_list = queryset_list.filter(city__iexact=city)
# Bedrooms
if 'bedrooms' in request.GET:
bedrooms = request.GET['bedrooms']
if 'bedrooms':
queryset_list = queryset_list.filter(bedrooms__lte=bedrooms)
# Price
if 'price' in request.GET:
price = request.GET['price']
if 'price':
queryset_list = queryset_list.filter(price__lte=price)
context = {
'state_choices': state_choices,
'bedroom_choices': bedroom_choices,
'price_choices': price_choices,
'listings': queryset_list,
'values': request.GET
}
return render(request, 'listings/search.html', context)
Here is my Template file..... for the Search..
{%extends 'base.html'%}
<!---Import Humanaize---->
{%load humanize %} {% block title %} | Search Results {%endblock%}
<!---- Start Block Content-->
{%block content%}
<section id="showcase-inner" class="showcase-search text-white py-5">
<div class="container">
<div class="row text-center">
<div class="col-md-12">
<form action="{%url 'search' %}">
<!-- Form Row 1 -->
<div class="form-row">
<div class="col-md-4 mb-3">
<label class="sr-only">Keywords</label>
<input type="text" name="keywords" class="form-control" placeholder="Keyword (Pool, Garage, etc)" value="{{values.keywords}}">
</div>
<div class="col-md-4 mb-3">
<label class="sr-only">City</label>
<input type="text" name="city" class="form-control" placeholder="City" value="{{values.city}}">
</div>
<div class="col-md-4 mb-3">
<label class="sr-only">State</label>
<select name="state" class="form-control">
<option selected="true" disabled="disabled">State (All)</option>
<!--loop through the key and value pairs-->
{%for key, value in state_choices.items %}
<option value="{{ key }}"
{% if key == values.state %}
selected
{%endif%}
>
{{ value }}</option>
{%endfor%}
</select>
</div>
</div>
<!-- Form Row 2 -->
<div class="form-row">
<div class="col-md-6 mb-3">
<label class="sr-only">Bedrooms</label>
<select name="bedrooms" class="form-control">
<option selected="true" disabled="disabled">Bedrooms (Any)</option>
<!--loop through the key and value pairs-->
{%for key, value in bedroom_choices.items %}
<option value="{{ key }}"
{% if key == values.bedrooms %}
selected
{%endif%}
>{{ value }}</option>
{%endfor%}
</select>
</div>
<div class="col-md-6 mb-3">
<select name="price" class="form-control">
<option selected="true" disabled="disabled">Max Price (All)</option>
<!--loop through the key and value pairs-->
{%for key, value in price_choices.items %}
<option value="{{ key }}"
{% if key == values.price %}
selected
{%endif%}
>
{{ value }}</option>
{%endfor%}
</select>
</div>
</div>
<button class="btn btn-secondary btn-block mt-4" type="submit">Submit form</button>
</form>
</div>
</div>
</div>
</section>
<!-- Breadcrumb -->
<section id="bc" class="mt-3">
<div class="container">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="{%url 'index'%}">
<i class="fas fa-home"></i> Home</a>
</li>
<li class="breadcrumb-item">
Browse Listings
</li>
<li class="breadcrumb-item active"> Search Results</li>
</ol>
</nav>
</div>
</section>
<!-- Listings -->
<section id="listings" class="py-4">
<div class="container">
<div class="row">
{%if listings %} {% for listing in listings %}
<!-- Listing 1 -->
<div class="col-md-6 col-lg-4 mb-4">
<div class="card listing-preview">
<img class="card-img-top" src="{{ listing.photo_main.url }}" alt="">
<div class="card-img-overlay">
<h2>
<span class="badge badge-secondary text-white">${{listing.price | intcomma}}</span>
</h2>
</div>
<div class="card-body">
<div class="listing-heading text-center">
<h4 class="text-primary">{{listing.title}}</h4>
<p>
<i class="fas fa-map-marker text-secondary"></i> {{listing.city}} {{listing.state}}, {{listing.zipcode}}</p>
</div>
<hr>
<div class="row py-2 text-secondary">
<div class="col-6">
<i class="fas fa-th-large"></i> Sqft: {{listing.sqft}}</div>
<div class="col-6">
<i class="fas fa-car"></i> Garage: {{listing.garage}}</div>
</div>
<div class="row py-2 text-secondary">
<div class="col-6">
<i class="fas fa-bed"></i> Bedrooms: {{listing.bedrooms}}</div>
<div class="col-6">
<i class="fas fa-bath"></i> Bathrooms: {{listing.bathrooms}}</div>
</div>
<hr>
<div class="row py-2 text-secondary">
<div class="col-12">
<i class="fas fa-user"></i> {{listing.realtor}}</div>
</div>
<div class="row text-secondary pb-2">
<div class="col-6">
<i class="fas fa-clock"></i> {{listing.list_date | timesince}}</div>
</div>
<hr>
More Info
</div>
</div>
</div>
{%endfor%}
<!----if above is not true------>
{%else%}
<div class="col-md-12">
<p>
No Listings Available
</p>
</div>
<!------end of the if statement ------>
{%endif%}
</div>
</div>
</section>
{%endblock%}
From what I see there is a small error in your view. A statement like
if 'keywords' in request.GET:
will not check whether 'keywords' is empty. I will always return True as long as there is a field called 'keywords' in your form.
Then your checks like
if 'keywords':
will always return True as you are not checking the variable but a string. What you probably mean is
if keywords:
to check if keywords contains something.
So what is currently happening is that - as all your checks are returning True - your are filtering your queryset using a lot of empty strings, and this will return an empty queryset.
So remove the '' from your checks like if 'keywords': and the other similar if statements.
If you want you can also remove the if 'keywords' in request.GET: and similar as they always return True.

Categories