Search function in Flask with SQLite - sqlite

I have a problem in my search function. The search result was not displayed in my web application. I'm trying to search words based on the brand or model. I have no idea what did I make mistake.
This is the backend in app.py
#app.route('/search',methods = ['GET','POST'])
def search():
result = request.form.get('search')
conn = get_db_connection()
searchsmartphones = conn.execute("SELECT * FROM Smartphone WHERE brand OR model = ?",(result,))
conn.commit()
return render_template('smartphone.html',searchsmartphones = searchsmartphones)
This is the search form
<form action="/search" method="GET">
<div class="mb-5 d-flex position-relative">
<!-- Search -->
<div class="input-group w-50 mx-auto">
<input class="form-control py-2" placeholder="Search for smartphone" name="search" value="" />
<button type="submit" class="btn btn-secondary text-muted">Search</button>
</div>
</div>
</form>
This is the output result
<div class="d-flex">
{% for smartphone in searchsmartphones %}
<div class="row row-cols-4 mb-5">
<div class="card mr-5" style="width: 20rem;">
<a href="#">
<img src="{{ url_for('static',filename = smartphone['image_URL']) }}" class="card-img-top" style="height: 250px;">
</a>
<div class="card-body">
<a href="#">
<h5 class="card-title">{{ smartphone['model'] }}</h5>
</a>
<div class="mt-5 d-flex justify-content-between">
<p class="text-muted">{{ smartphone['brand'] }}</p>
<p class="fw-bold">{{ smartphone['lowprice'] }} - {{ smartphone['highprice'] }}</p>
</div>
</div>
</div>
</div>
<div class="col-md-auto">
</div>
{% endfor %}
</div>
Traceback (most recent call last):
File "C:\Users\user\desktop\phonebuddy\.venv\lib\site-packages\flask\app.py", line 2525, in wsgi_app
response = self.full_dispatch_request()
File "C:\Users\user\desktop\phonebuddy\.venv\lib\site-packages\flask\app.py", line 1822, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Users\user\desktop\phonebuddy\.venv\lib\site-packages\flask\app.py", line 1820, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\user\desktop\phonebuddy\.venv\lib\site-packages\flask\app.py", line 1796, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
File "C:\Users\user\Desktop\PhoneBuddy\app.py", line 94, in search
searchsmartphones = conn.execute("SELECT * FROM Smartphone WHERE brand LIKE '%?%' OR model LIKE '%?%'",(result,result))
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 0, and there are 2 supplied.
127.0.0.1 - - [27/Nov/2022 22:15:14] "GET /search?search=Apple&sort=low HTTP/1.1" 500 -
Empty when using my original code

The error indicates that we did not pass enough parameters to the select query. I found that we cannot use %?% directly.
Example of using Flask and Sqlite3 for search query
I reproduced the scenario with dummy data and dummy SQL schema. The SQL schema and dummy query insertion happens at the first view of the root / path. The search path is defined in /search route.
File structure:
.
├── app.py
├── mobile_devices.db
├── schema.sql
├── templates
│   ├── home.html
│   └── search.html
schema.sql:
CREATE TABLE IF NOT EXISTS Smartphone (
id INTEGER PRIMARY KEY AUTOINCREMENT,
brand TEXT NOT NULL,
model TEXT NOT NULL,
lowprice DOUBLE NOT NULL
);
app.py:
from flask import Flask, render_template, g, request
import sqlite3
DATABASE = 'mobile_devices.db'
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your secret key'
def get_db():
db = getattr(g, '_database', None)
if db is None:
db = g._database = sqlite3.connect(DATABASE)
db.row_factory = sqlite3.Row
return db
#app.teardown_appcontext
def close_connection(exception):
db = getattr(g, '_database', None)
if db is not None:
db.close()
def query_db(query, args=(), one=False):
cur = get_db().execute(query, args)
rv = cur.fetchall()
cur.close()
return (rv[0] if rv else None) if one else rv
def insert_db(query, args=()):
msg = ""
with app.app_context():
try:
db = get_db()
cur = db.cursor()
cur.execute(query, args)
db.commit()
msg = "Insertion successful"
except Exception as ex:
msg = f"Insertion failed: {str(ex)}"
finally:
print(msg)
def init_db():
with app.app_context():
db = get_db()
with app.open_resource('schema.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()
init_db()
def insert_dummy_values():
insert_db(
"INSERT INTO Smartphone (brand, model, lowprice) VALUES (?,?,?)",
("Nokia", "C6", 150))
insert_db(
"INSERT INTO Smartphone (brand, model, lowprice) VALUES (?,?,?)",
("Samsung", "Fold", 250))
insert_db(
"INSERT INTO Smartphone (brand, model, lowprice) VALUES (?,?,?)",
("Nokia", "N95", 300))
insert_db(
"INSERT INTO Smartphone (brand, model, lowprice) VALUES (?,?,?)",
("Sony", "Samsung", 1250))
#app.route('/')
def show_home():
smart_phones = query_db('select brand, model, lowprice from Smartphone')
if len(smart_phones) == 0:
insert_dummy_values()
smart_phones = query_db('select brand, model, lowprice from Smartphone')
return render_template('home.html', smart_phones=smart_phones)
#app.route('/search', methods=['GET', 'POST'])
def search():
if request.method == "POST":
search_value = request.form.get('search_brand_model')
print(search_value)
smart_phones = query_db(
"SELECT * FROM Smartphone WHERE brand LIKE ? OR model LIKE ?",
('%' + search_value + '%', '%' + search_value + '%'))
return render_template('search.html', searchsmartphones=smart_phones)
else:
return render_template('search.html')
templates/home.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
{% if smart_phones%}
Total smartphones in DB: {{ smart_phones | length }}
<ul>
{% for smartphone in smart_phones %}
<li> {{ smartphone['brand'] }} {{ smartphone['model'] }} :
${{ smartphone['lowprice'] }}
</li>
{% endfor %}
</ul>
{% else %}
<p>No smartphone in db</p>
{% endif %}
</body>
</html>
templates/search.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Search</title>
</head>
<body>
<form action="/search" method="POST">
<div class="mb-5 d-flex position-relative">
<!-- Search -->
<div class="input-group w-50 mx-auto">
<input class="form-control py-2"
placeholder="Search for smartphone" name="search_brand_model" value=""/>
<button type="submit" class="btn btn-secondary text-muted">Search
</button>
</div>
</div>
</form>
{% if searchsmartphones %}
<div class="d-flex">
{% for smartphone in searchsmartphones %}
<div class="row row-cols-4 mb-5">
<div class="card mr-5" style="width: 20rem;">
<div class="card-body">
<a href="#">
<h5 class="card-title">{{ smartphone['model'] }}</h5>
</a>
<div class="mt-5 d-flex justify-content-between">
<p class="text-muted">{{ smartphone['brand'] }}</p>
<p class="fw-bold">{{ smartphone['lowprice'] }}</p>
</div>
</div>
</div>
</div>
<div class="col-md-auto">
</div>
{% endfor %}
</div>
{% endif %}
</body>
</html>
Screenshots:
Initial database rows:
Search using Brand Nokia:
Search using model n95:

Related

Flask-WTForms .validate_on_submit() never executes

So basically I want to have a Updateform() form that allows users to update their account details. All my other forms (register, etc.) work perfectly fine but this specific form never validates on submit. Hence when I press the submit button the page just refreshes but the .validate_on_submit() code doesn't execute.
I've looked through the forums and a common issue I found is the .CSRF token missing, but I'm using form.hidden_tag() which I read should work perfectly fine. So it seems that my issue is unique.
I've been looking on the forums for hours but haven't found a solution.
Here is my form code:
class Updateform(FlaskForm):
email = StringField('Email:', validators=[DataRequired(), Email()])
picture = FileField('Update Profile Picture:', validators=[FileAllowed(['jpg', 'png'])])
submit = SubmitField("Update")
def validate_email(self, email):
if email.data != User.email:
if User.query.filter_by(email=email.data).first():
raise ValidationError('Email has already been registered')
Here is the route:
#users.route('/account', methods=['GET', 'POST'])
#login_required
def account():
form = Updateform()
print("hello")
if form.validate_on_submit():
print(form)
print("YES!!!")
name = current_user.name
pic = add_profile_pic(form.picture.data, name)
current_user.profile_image = pic
current_user.email = form.email.data
db.session.commit()
flash("Account Updated")
# elif request.method == "GET":
# form.email = current_user.email
profile_image = url_for('static', filename='profile_pics/'+current_user.profile_image)
return render_template('account.html', profile_image=profile_image, form=form)
And here is the html code:
{% extends "base.html" %}
{% block content %}
<div align="center">
Hi {{ current_user.name }}<br>
<img align="center" src="{{ url_for('static', filename='profile_pics/'+current_user.profile_image) }}">
</div>
<div class="container">
<form method="post">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.email.label(class='form-group') }}
{{ form.email(class='form-control') }}
</div>
<div class="form-group">
{{ form.picture.label(class='form-group') }}
{{ form.picture(class='form-control') }}
</div>
<div class="form-group">
{{ form.submit() }}
</div>
</form>
</div>
{% endblock %}
The extra classes you see are from the bootstrap library incase anyone is wondering.
Hello you could find out what the problem is by adding a else for you if form.validate_on_submit(): and have it do this
for error in form.email.errors:
print(error)
for error in form.picture.errors:
print(error)
this should tell you what is not working hope this helps and I have not tested this so it could have typos

Can't extend data from Pin model

My models.py looks like this.
model.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class Pin(models.Model):
proffession = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.proffession
def get_absolute_url(self):
return reverse('pin-detail', kwargs={'pk': self.pk})
Views.py
def home(request):
context = {
'pins': Pin.objects.all(),
}
def get(self, request):
users = User.objects.exclude(id=request.user.id)
return render(request, 'vlog/home.html')
return render(request, 'vlog/home.html', context)
class PinListView(ListView):
model = Pin
template_name = 'vlog/home.html' # <app>/<model>_<view_type>.html
context_object_name = 'pins'
ordering = ['-date_posted']
paginate_by = 5
While extending data from Pin model. It doesn't provide any result.
base.html
<div class="col-md-4">
<div class="content-section">
<h3>Available People</h3>
{% for pin in pins %}
<article class="media content-section">
<!-- <img class="rounded-circle article-img" src="{{ post.author.profile.image.url }}"> -->
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'profileu' %}">{{ pin.username }}</a>
</div>
<p class="article-metadata">{{ pin.content }}</p>
</div>
</article>
{% endfor %}
</div>
</div>
How can I extend data from Pin Model in ListView. Please Share your suggestion

Multiple file upload constraint

I'm followed the tutorial to manage the upload of multiple files http://growingcookies.com/easy-multiple-file-upload-in-symfony-using-the-collectiontype-field/
The system for uploading multiple files works fine.
However, I would like to add a constraint to allow only certain types of files and to set a maximum size.
For that, I add #Assert\File:
/**
* #Assert\File(
* maxSize = "300k",
* mimeTypes = {"application/pdf", "application/x-pdf", "text/plain", "application/msword",
* "application/vnd.ms-excel", "image/jpeg", "image/x-citrix-jpeg", "image/png", "image/x-citrix-png", "image/x-png", "image/gif",
* "application/zip"},
* mimeTypesMessage = "Liste des formats de fichiers acceptés : PDF, TXT, DOC, XLS, JPG, PNG, GIF"
* )
*
* #ORM\OneToMany(targetEntity="Maps_red\TicketingBundle\Entity\TicketDocument", mappedBy="ticket", cascade={"persist"}, orphanRemoval=true)
*/
protected $documents;
By adding that, the code does not work anymore. I get the following error :
Impossible to access an attribute ("name") on a null variable.
This error appears on the Add Files page when I send the form. The line corresponding to the error is:
<div class="col col-xs-11" id="jsPreview{{ pos }}">{{ doc.vars.value.name }}</div>
The constraint violation message is : "The file could not be found."
Do you know where my error is ?
Edit for #Denis Alimov:
I tried the answer of Denis Alimov with #Assert\All but it returns the same error.
I then tried to put the constraint in the BuildForm. Now, the .txt files pass without error, but all the other extensions always return me the same error
Impossible to access an attribute ("name") on a null variable.
Edit for #Jakumi:
My twig :
{% extends '#Ticketing/base.html.twig' %}
{% block title %}{{ 'New Ticket'|trans({}, 'TicketingBundle') }}{% endblock %}
{% block header %}<h1>{{ 'New Ticket'|trans({}, 'TicketingBundle') }}</h1>{% endblock %}
{% block form_group_class -%}
col-sm-8
{%- endblock form_group_class %}
{% block main %}
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
{% form_theme form 'bootstrap_4_layout.html.twig' _self %}
<div class="box box-danger">
<div class="box-header with-border">
<h3 class="box-title">{{ 'Create a new ticket'|trans({}, 'TicketingBundle') }}</h3>
</div>
{% form_theme form 'bootstrap_3_horizontal_layout.html.twig' _self %}
{{ form_start(form, {'attr': {'class': 'form-horizontal'} }) }}
<div class="box-body">
<div class="hr-line-dashed"></div>
<div id="filesProto" data-prototype="{{ form_widget(form.documents.vars.prototype)|e }}"></div>
<div class="form-group">
<label class="col-sm-2 control-label" for="ticket_form_documents">Pièce-jointe</label>
<div class="col-sm-8" id="filesBox">
{% set pos = 0 %}
{% for doc in form.documents %}
<div class="row">
<div class="col col-xs-1" id="jsRemove{{ pos }}" style="">
<button type="button" class="btn btn-danger" onclick="removeFile($(this));"><i class="fa fa-times" aria-hidden="true"></i></button>
</div>
<div class="col col-xs-11" id="jsPreview{{ pos }}">{{ doc.vars.value.name }}</div>
<div style="display:none">
{{ form_widget(doc) }}
</div>
</div>
{% set pos = pos + 1 %}
{% endfor %}
</div>
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
<div class="col-md-offset-2 col-sm-8">
<button id="dropbutton" class="btn bg-ticketing btn-flat form-control" type="submit">
{{ 'Submit the ticket'|trans({}, 'TicketingBundle') }}
</button>
</div>
</div>
<!-- /.box-footer -->
{{ form_end(form) }}
</div>
<script>
var fileCount = '{{ form.documents|length }}';
var removeButton = "<button type='button' class='btn btn-danger btn-xs' onclick='removeFile($(this));'><i class='fa fa-times' aria-hidden='true'></i></button>";
function removeFile(ob)
{
ob.parent().parent().remove();
}
function createAddFile(fileCount)
{
// grab the prototype template
var newWidget = $("#filesProto").attr('data-prototype');
// replace the "__name__" used in the id and name of the prototype
newWidget = newWidget.replace(/__name__/g, fileCount);
newWidget = "<div style='display:none'>" + newWidget + "</div>";
hideStuff = "";
hideStuff += "<div class='col col-xs-1' id='jsRemove" + fileCount + "' style='display: none;'>";
hideStuff += removeButton;
hideStuff += "</div>";
hideStuff += "<div class='col col-xs-11' id='jsPreview" + fileCount + "'>";
hideStuff += "</div>";
hideStuff += "<div class='col-sm-8'>";
hideStuff += "<button type='button' id='jsBtnUpload" + fileCount + "' class='btn btn-default'>";
hideStuff += "<i class='fa fa-plus'></i> {{ 'Pièce-jointe' | trans }}";
hideStuff += "</button>";
hideStuff += "</div>";
$("#filesBox").append("<div class='form-group'>" + hideStuff + newWidget + "</div>");
// On click => Simulate file behaviour
$("#jsBtnUpload" + fileCount).on('click', function(e){
$('#ticket_form_documents_' + fileCount + '_file').trigger('click');
});
// Once the file is added
$('#ticket_form_documents_' + fileCount + '_file').on('change', function() {
// Show its name
fileName = $(this).prop('files')[0].name;
$("#jsPreview" + fileCount).append(fileName);
// Hide the add file button
$("#jsBtnUpload" + fileCount).hide();
// Show the remove file button
$("#jsRemove" + fileCount).show();
// Create another instance of add file button and company
createAddFile(parseInt(fileCount)+1);
});
}
$(document).ready(function(){
createAddFile(fileCount);
fileCount++;
});
</script>
{% endblock %}
Edit :
With {{ doc.vars.value.name ?? '' }} I do not have the error anymore !!
However, the file deletion buttons remain displayed:
<div class="col col-xs-1" id="jsRemove1" style="">
<button type="button" class="btn btn-danger" onclick="removeFile($(this));"><i class="fa fa-times" aria-hidden="true"></i></button>
</div>
How to make these buttons disappear when a file type is not good?
As already mentioned use All constraint like this
/**
* #Assert\All({
* #Assert\File(
* maxSize = "300k",
* mimeTypes = {"application/pdf", "application/x-pdf", "text/plain", "application/msword", "application/vnd.ms-excel", "image/jpeg", "image/x-citrix-jpeg", "image/png", "image/x-citrix-png", "image/x-png", "image/gif","application/zip"},
* mimeTypesMessage = "Liste des formats de fichiers acceptés : PDF, TXT, DOC, XLS, JPG, PNG, GIF"
* )
* })
*/
private $documents;
Also you can add constraints to your DocumentType in the buildForm method

Linking Title to an URL in drupal

I am just new to Drupal and trying to update some existing applications. I am trying to associate the title to an URL. I tried this
link(title, content.field_url)
But I don't think I am right track. Any help would be appreciated. Following is the twig templet for displaying persons.
<div class="wdn-col" style="margin-top:2.4em;">
<div class="wdn-grid-set">
<div class="wdn-col-three-sevenths">
<div class="wdn-frame">{{ (content.field_portrait) }}</div>
</div>
<div class="wdn-col-four-sevenths">
<h5 class="wdn-brand clear-top">{{title }}
<span class="wdn-subhead">{{ (content.field_position) }}, {{ (content.field_institution) }}</span></h5>
<p style="font-size:smaller;">{{ (content.field_unit) }}</p>
<p>{{ (content.field_email_address) }}</p>
</div>
</div>
</div>
Try like this way....
{{ title }}

Show available rooms through Status

We have an asp.net hotel room reservation project and I have difficulties in showing the rooms through its status. So if the user will book a room, it will reflect 'In' status in the table. And now, I tried to show the rooms which doesn't have 'In' Status and instead, show the rooms which have 'Out' status. Here is the code that I've been dying to fix:
<%
Dim MyConnNew As OdbcConnection
Dim MyCommNew As OdbcCommand
Dim MyDataReadNew As OdbcDataReader
Dim logic As Integer = 0
MyConnNew = New OdbcConnection("DRIVER={MySQL ODBC 3.51 Driver};Database=hotelsdb;Server=localhost;UID=root;")
MyConnNew.Open()
If MyConnNew.State = 0 Then
MyConnNew.Open()
End If
MyCommNew = New OdbcCommand("select * from hotelbookings where status ='" + "Out" + "'", MyConnNew)
MyDataReadNew = MyCommNew.ExecuteReader()
Dim roomParams As New List(Of Integer)()
While (MyDataReadNew.Read())
If MyDataReadNew.Item("roomid") <> 0 Then
roomParams.Add(MyDataReadNew.Item("roomid"))
logic = 1
End If
End While
Dim roomArray() As Integer = roomParams.ToArray()
If logic <> 0 Then
MyCommNew = New OdbcCommand("select * from hotelrooms", MyConnNew)
MyDataReadNew = MyCommNew.ExecuteReader()
Dim valid As Boolean
valid = False
While (MyDataReadNew.Read())
For i As Integer = 0 To roomArray.Length - 1
If MyDataReadNew.Item("roomid") = roomArray(i) Then
valid = True
End If
Next
If valid <> True Then
%>
<div class="col-xs-12 col-sm-4 col-md-4">
<input type="hidden" value="<%Response.Write(MyDataReadNew.Item("roomid"))%>"/>
<div class="grid wow zoomIn">
<figure class="effect-bubba">
<a href="Rooms.aspx">
<img src="assets/images/<%Response.Write(MyDataReadNew.Item("roomimage"))%>"/>
</a>
</figure>
<div class="text-left">
<input type="hidden" value="<%Response.Write(MyDataReadNew.Item("roomnumber"))%>" />
<ul class="list-unstyled">
<li><h2><%Response.Write(MyDataReadNew.Item("roomtype"))%> Room</h2></li>
<li><b>Adults:</b> Up to 3 adult(s)</li>
<li><b>Children (0-12 yrs old):</b> Free</li>
<li><b>Starting rate per night:</b> <%Response.Write(MyDataReadNew.Item("roomrate"))%> php</li>
<li><a class="btn btn-primary" href="insertreservation.aspx?room_id=<% Response.Write(MyDataReadNew.Item("roomid"))%>" >Reserve</a><br/></li>
</ul>
</div>
</div>
</div>
<nav id="myscroll" class="navbar navbar-default navbar-static top" role="navigation">
<h2>Select Available rooms</h2>
<div class="alert alert-info"><p><b>All rooms have:</b> 40-inch LED HDTV with cable channels• Media panel with HDMI, USB and A/V connectivity• Speaker Phone with iPod dock and FM Stereo• Executive Writing Desk• Complimentary Wi-Fi</p>
</div>
</nav>
<div data-spy="scroll" data-target="#myscroll" data-offset="0" style="height:500px;overflow:auto; position: relative;">
<div class="container">
<%While (MyDataReadNew.Read())%>
<div class="col-xs-12 col-sm-4 col-md-4">
<input type="hidden" value="<%Response.Write(MyDataReadNew.Item("roomid"))%>"/>
<div class="grid wow zoomIn">
<figure class="effect-bubba">
<a href="Rooms.aspx">
<img src="assets/images/<%Response.Write(MyDataReadNew.Item("roomimage"))%>"/>
</a>
</figure>
<div class="text-left">
<input type="hidden" value="<%Response.Write(MyDataReadNew.Item("roomnumber"))%>" />
<ul class="list-unstyled">
<li><h2><%Response.Write(MyDataReadNew.Item("roomtype"))%> Room</h2></li>
<li><b>Adults:</b> Up to 3 adult(s)</li>
<li><b>Children (0-12 yrs old):</b> Free</li>
<li><b>Starting rate per night:</b> <%Response.Write(MyDataReadNew.Item("roomrate"))%> php</li>
<li><a class="btn btn-primary" href="insertreservation.aspx?roomid=<% Response.Write(MyDataReadNew.Item("roomid"))%>" >Reserve</a><br/></li>
</ul>
</div>
</div>
</div>
<%
End While
End If
MyDataReadNew.Close()
MyConnNew.Close()
%>
</div>
Hope you'll help with this :) Thanks
First of all, instead of two queries, you can write:
Select distinct hotelrooms.roomid, hotelrooms.roomimage, hotelrooms.roomtype --other fields here
from hotelbookings
left outer join hotelrooms on hotelrooms.roomid=hotelbookings.roomid
where hotelbookings.status ='Out'
or
select *
from hotelrooms
where roomid in --or 'not in'
(select hotelbookings.roomid
from hotelbookings
where hotelbookings.status ='Out')
Then we need tables structure.
I can't understand why you post
<div class="col-xs-12 col-sm-4 col-md-4">...</div>
maybe it's not related to your question.

Resources