How to display flask data on URL path - python

hi I created a simple website to calculate the square of the number. below is the code
calculate.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="homepage.css">
<title>Flask </title>
</head>
<body>
<header>
square
</header>
<div class="congrat">
{{ result }}
</div>
</body>
</html>
homepage.html
<form method="post" action="/square">
<div class="calculate">
<b>Square</b><br/>Num
<input type="text" name="number"><br/>
<input type="submit" value="calculate">
</div>
</form>
python
#app.route("/square", methods=['POST'])
def square():
number = request.form["number"]
return render_template("calculate.html", result = int(number) ** 2)
now I want to display input number in URL path. e.g. http://127.0.0.1:3000/square/10
so I've tried this
<form method="post" action="/square/<number>">
<div class="calculate">
<b>Square</b><br/>Num
<input type="text" name="number"><br/>
<input type="submit" value="calculate">
</div>
</form>
#app.route("/square/<number>", methods=['POST'])
def square(number):
number = request.form["number"]
return render_template("calculate.html", result = int(number) ** 2)
but it didn't work. What could I do?

You could get variables directly parsed from Flask URL
#app.route("/square/<number>", methods=['POST'])
def square(number):
return render_template("calculate.html", result = int(number) ** 2)
Edit:
<form id="your_form" method="post" onsubmit="yourFunction()">
<input type="text" name="keywords">
<input type="text" name="number"><br/>
<input type="submit" value="calculate">
</form>
<script>
function yourFunction(){
var action_src = "/square/" + document.getElementsByName("number")[0].value;
var your_form = document.getElementById('your_form');
your_form.action = action_src ;
}
</script>

Related

Flask update html with data from POST

i'm learning Flask/Ajax.
In a POST method i read some data from pwstest.html to run a python script.
Following the Python
#wApp.route("/pwstest",methods=\['GET','POST'\])
def index():
titlepage ='Page title
stato=''
args, data, method = fjrh.handleRequest(request,auth=False)`
if method =='POST':
stato = ''
output = request.get_json()
result = json.loads(output)
logging.info(result)
utente = result\['testoinput'\]
identificativo = result\['numeroinput'\]
dataestrazione = result\['datainput'\]
format='%Y-%m-%d'
dataestrdate = datetime.strptime(dataestrazione,format)
datastr= dataestrdate.strftime("%d-%m-%Y")
parziale= result\['datacheck'\]
if parziale == 'on':`
stringpws = 'http://192.168.x.xxx:5009/plan?diff=True&data=' + datastr
else:
stringpws = 'http://192.168.x.xxx:5009/plan?diff=False&data=01-01-2000'
sqlqry= """select dbo.Callfunction (:1) as result"""
par = (stringpws,)
mApp = MainApp(sql,yyy,mail,walker,parRun, logger)
message= mApp.plan(sqlqry,par)
stato=jsonify(message)
logging.info(stato.status)
return jsonify({"valorestato":message})
else:
return render_template('pwstest.html',nome=titlepage, valorestato=stato)`
And the pwstest.html
<!doctype html>
<html>
<head>
<meta name="description" content="Form di Inserimento di Test">
<meta name="keywords" content="form Inserimento per Test">
<link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='main.css') }}">
</head>
<body>
<dt>
<div>
<form class="'form-signin">
<label for="inputtext" class="sr-only">Addetto</label>
<input type="text" name="inputtext" id="inputtext" class="form-control" placeholder="Nome e Cognome" required autofocus>
</form>
<form>
<label for="inputnumber" class="sr-only">Identificativo</label>
<input type="number" name="inputnumber" id="inputnumber" class="form-control" placeholder="Numero Addetto" required autofocus>
</form>
<form>
<label for="inputrec" class="sr-only">Recalc Date</label>
<input type="date" name="inputdate" id="inputdate" class="form-control" placeholder="Recalc from date" required>
</form>
<form>
<label for="inputflag" class="sr-only">Partial</label>
<input type="checkbox" name="inputflag" id="inputflag" class="form-control" placeholder="Partial" required>
</form>
<form>
<button id="btnSignUp" onclick= 'prelievo();' class="btn btn-lg btn-primary btn-block" type="button">Elabora</button>
</form>
</div>
<div id="finale">
{{valorestato}}
</div>
</dt>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
<script>
function prelievo() {
const testoinput = document.getElementById("inputtext").value;
const numeroinput = document.getElementById("inputnumber").value;
const datainput = document.getElementById("inputdate").value;
const datacheck = document.getElementById("inputflag").value;
const dict_values = {testoinput, numeroinput,datainput,datacheck}
const s = JSON.stringify(dict_values);
var workingstatus = 'In Elaborazione'
document.getElementById("finale").innerHTML=workingstatus
console.log(s);
$.ajax({
url:"/pwstest",
type:"POST",
contentType: "application/json",
data: JSON.stringify(s)
})
}
When the script return the results, i need to update the Html page with the result.
Seems the return render_template won't works in the POST method.
Could you help me?
Thank you in advance.

Dango - show title from multiple models in autocomplete search bar

I want to display titles from 2 models in my autocomplete feature in the search bar, however, I am not sure how to write a loop in search_address_qa function that would display titles from multiple models.
For now, I can only properly display address_objects (Article) or address_objects_qa(QA) but not both. The results from search_items are fine. When I try to put for address_object in address_objects_qa or address_objects then I get some random results.
models.py
class QA(models.Model):
title=models.CharField(max_length=1000, help_text='max 1000 characters')
body = RichTextField(verbose_name='Description', blank=True)
class Article(models.Model):
title=models.CharField(max_length=1000, help_text='max 1000 characters')
body = RichTextField(verbose_name='Description', blank=True)
views.py
#login_required
def search_address_qa(request):
query = request.GET.get('title')
payload = []
if query:
lookups = Q(title__icontains=query)
address_objects = Article.objects.filter(lookups, status=1)
address_objects_qa = QA.objects.filter(lookups, status=1)
for address_object in address_objects_qa:
payload.append(address_object.title)
return JsonResponse({'status':200, 'data': payload})
#login_required
def search_items(request):
query = request.GET.get('q')
article = Article.objects.filter(title__icontains=query)
qa_list = QA.objects.filter(title__icontains=query)
if query is not None:
lookups = Q(title__icontains=query) |Q(body__icontains=query)
article = Article.objects.filter(lookups).distinct()
qa_list = QA.objects.filter(lookups).distinct()
context = {
'query_name': query,
'search_items': article,
'qa_list': qa_list,
}
return render(request, 'search/search_items.html', context)
search_items.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=yes" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
<link rel="stylesheet" href="https://unpkg.com/#trevoreyre/autocomplete-js/dist/style.css" />
</head>
<body>
<main class="container-fluid">
<!--HEADER-->
<header class="header" id="header">
<h3 class="col-6">Search results for: {{ query_name }}</h3>
<!--SEARCH BAR-->
<button class="col-6" onclick="openSearch()"><i class="fas fa-search fa-sm"></i></button>
<form action="{% url 'search_items' %}" method="get" id="search">
{% csrf_token %}
<div class="searchbar" id="autocomplete">
<input name="q" type="text" placeholder="Search..." class="search_input">
<button class="search_icon"><i class="fas fa-search fa-sm"></i></button>
<ul class="autocomplete-result-list"></ul>
</div>
</form>
<!--END SEARCH BAR-->
</header>
<!--END HEADER-->
{% if qa_list %}
<section class="py-3">
<h2>Q&A's</h2>
<hr>
<div class="row">
{% for qa in qa_list %}
<div class="col-10">
{{qa.title}}
</div>
{% endfor %}
</div>
</section>
{% endif %}
{% if search_items %}
<section class="py-3">
<h2>Q&A's</h2>
<hr>
<div class="row">
{% for article in search_items %}
<div class="col-10">
{{article.title}}
</div>
{% endfor %}
</div>
</section>
{% endif %}
</main>
<!--JS files-->
<script src="https://unpkg.com/#trevoreyre/autocomplete-js"></script>
As suggested in comments I used itertools.chain to iterate over 2 models. I am posting the code below. Maybe it will be useful for someone.
from itertools import chain
#login_required
def search_title(request):
query = request.GET.get('title')
payload = []
if query:
lookups = Q(title__icontains=query)
optimazon_titles = Article.objects.filter(lookups, status=1)
qa_titles = QA.objects.filter(lookups, status=1)
payload = map(lambda x: x.title, chain(optimazon_titles, qa_titles))
return JsonResponse({'status':200, 'data': list(payload)})

ValueError: Cannot convert mixed to alternative - Sending Email with Python

I am trying to send a styled bootstrap HTML template to email with the help of smtplib and EmailMessage. I have used f string to format the file. But, I am facing ValueError: Cannot convert mixed to the alternative. I could not address the problem. It should have work but couldn't be able to think much. Where did I do wrong?.
In emailsender.py
import smtplib
import imghdr
from email.message import EmailMessage
#Credentials
sender_email = "sender127#gmail.com"
password = 'password231'
receiver_email = "reciever9882#gmail.com"
smtp = smtplib.SMTP_SSL('smtp.gmail.com',465)
smtp.login(sender_email, password)
message = EmailMessage() #Instantiate EmailMessage
with open('/email.png', 'rb') as file_obj:
fdata = file_obj.read()
ftype = imghdr.what(file_obj.name)
print('Type:'+ftype)
fname = file_obj.name
print('Name of file:'+fname)
message["Subject"] = "Email Test"
message["From"] = sender_email
message["To"] = receiver_email
message.set_content("This is a test version!")
#message.attach('django notes.pdf')
message.add_attachment(fdata, maintype ="image", subtype = ftype,
filename=fname)
message.add_alternative(f"""\n\n
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<div class="container py-4">
<header class="pb-3 mb-4 border-bottom">
<a href="/" class="d-flex align-items-center text-dark text-decoration-none">
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="32" class="me-2" viewBox="0 0 118 94"
role="img">
<title>Bootstrap</title>
<path fill-rule="evenodd" clip-rule="evenodd"
d="M24.509 0c-6.733 0-11.715 5.893-11.492 12.284.214 6.14-.064 14.092-2.066 20.577C8.943 39.365 5.547 43.485 0 44.014v5.972c5.547.529 8.943 4.649 10.951 11.153 2.002 6.485 2.28 14.437 2.066 20.577C12.794 88.106 17.776 94 24.51 94H93.5c6.733 0 11.714-5.893 11.491-12.284-.214-6.14.064-14.092 2.066-20.577 2.009-6.504 5.396-10.624 10.943-11.153v-5.972c-5.547-.529-8.934-4.649-10.943-11.153-2.002-6.484-2.28-14.437-2.066-20.577C105.214 5.894 100.233 0 93.5 0H24.508zM80 57.863C80 66.663 73.436 72 62.543 72H44a2 2 0 01-2-2V24a2 2 0 012-2h18.437c9.083 0 15.044 4.92 15.044 12.474 0 5.302-4.01 10.049-9.119 10.88v.277C75.317 46.394 80 51.21 80 57.863zM60.521 28.34H49.948v14.934h8.905c6.884 0 10.68-2.772 10.68-7.727 0-4.643-3.264-7.207-9.012-7.207zM49.948 49.2v16.458H60.91c7.167 0 10.964-2.876 10.964-8.281 0-5.406-3.903-8.178-11.425-8.178H49.948z"
fill="currentColor"></path>
</svg>
<span class="fs-4">Jumbotron example</span>
</a>
</header>
<div class="p-5 mb-4 bg-light rounded-3">
<div class="container-fluid py-5">
<h1 class="display-5 fw-bold">Custom jumbotron</h1>
<p class="col-md-8 fs-4">Using a series of utilities, you can create this jumbotron, just like the one
in previous versions of Bootstrap. Check out the examples below for how you can remix and restyle it
to your liking.</p>
<button class="btn btn-primary btn-lg" type="button">Example button</button>
</div>
</div>
<div class="row align-items-md-stretch">
<div class="col-md-6">
<div class="h-100 p-5 text-white bg-dark rounded-3">
<h2>Change the background</h2>
<p>Swap the background-color utility and add a `.text-*` color utility to mix up the jumbotron look.
Then, mix and match with additional component themes and more.</p>
<button class="btn btn-outline-light" type="button">Example button</button>
</div>
</div>
<div class="col-md-6">
<div class="h-100 p-5 bg-light border rounded-3">
<h2>Add borders</h2>
<p>Or, keep it light and add a border for some added definition to the boundaries of your content.
Be sure to look under the hood at the source HTML here as we've adjusted the alignment and
sizing of both column's content for equal-height.</p>
<button class="btn btn-outline-secondary" type="button">Example button</button>
</div>
</div>
</div>
<footer class="pt-3 mt-4 text-muted border-top">
© 2021
</footer>
</div>
<script src="https://cdn.jsdelivr.net/npm/#popperjs/core#2.10.2/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/js/bootstrap.min.js"></script>
</body>
</html>
""" ,subtype="html")
smtp.send_message(message)
Tracebacks here->
click here to view the traceback

How can I append data from html to array in views from a button?

I'm trying to build a website that generates a power hour style video from a list of music videos that the user selects by searching through the youtube api. I'm having trouble figuring out how to append selected videos to a list (addedVideos) in view.py from a button (add) in my html. I need to append each added video to a list so I can display them and loop through them in an embedded youtube player. This is my first django project so I don't have a good understanding of what the potential problems could be. index.html and views.py below:
views.py
import requests
from isodate import parse_duration
from django.conf import settings
from django.shortcuts import render, redirect
def index(request):
addedVideos = []
videos = []
if request.method == 'POST':
search_url = 'https://www.googleapis.com/youtube/v3/search'
video_url = 'https://www.googleapis.com/youtube/v3/videos'
search_params = {
'part' : 'snippet',
'q' : request.POST['search'],
'key' : settings.YOUTUBE_DATA_API_KEY,
'maxResults' : 3,
'type' : 'video'
}
#print(request.POST['submit'])
r = requests.get(search_url, params=search_params)
#print(r)
results = r.json()['items']
#print(results)
video_ids = []
for result in results:
video_ids.append(result['id']['videoId'])
if request.POST['submit'] == 'lucky':
return redirect(f'https://www.youtube.com/watch?v={ video_ids[0] }')
video_params = {
'key' : settings.YOUTUBE_DATA_API_KEY,
'part' : 'snippet,contentDetails',
'id' : ','.join(video_ids),
'maxResults' : 3
}
r = requests.get(video_url, params=video_params)
results = r.json()['items']
for result in results:
video_data = {
'title' : result['snippet']['title'],
'id' : result['id'],
'url' : f'https://www.youtube.com/watch?v={ result["id"] }',
'duration' : int(parse_duration(result['contentDetails']['duration']).total_seconds() // 60),
'thumbnail' : result['snippet']['thumbnails']['high']['url']
}
videos.append(video_data)
if request.POST['add'] == 'addValue':
print("add clicked")
context = {
'videos' : videos,
'addedVideos': addedVideos
}
return render(request, 'search/index.html', context)
index.html
{% load static %}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Search YouTube</title>
<!-- Bootstrap core CSS -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<style>
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
#media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
</style>
<!-- Custom styles for this template -->
<link href="{% static 'search/album.css' %}" rel="stylesheet">
</head>
<body>
<main role="main">
<section class="jumbotron text-center">
<div class="container">
<h1 class="jumbotron-heading">Build Your Power Hour</h1>
<p class="lead text-muted">Select music videos to add to your power hour</p>
<form method="POST">
<div class="input-group mb-3">
{% csrf_token %}
<input type="text" name="search" class="form-control" aria-label="Username">
</div>
<p>
<button type="submit" name="submit" value="search" class="btn btn-primary my-2">YouTube Search</button>
<button type="submit" name="submit" value="lucky" class="btn btn-secondary my-2">I'm Feeling Lucky</button>
</p>
</form>
</div>
</section>
<div class="album py-5 bg-light">
<div class="container">
<div class="row">
{% for video in videos %}
<div class="col-md-4">
<div class="card mb-4 shadow-sm">
<img class="bd-placeholder-img card-img-top" width="100%" height="225" src="{{ video.thumbnail }}" preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: Thumbnail"></img>
<div class="card-body">
<p class="card-text">{{ video.title }}</p>
<div class="d-flex justify-content-between align-items-center">
<div class="btn-group">
<form method="POST">
{% csrf_token %}
<button type="submit" name="add" value="addValue" id='{{ video }}' class="btn btn-sm btn-outline-secondary">Add</button>
</form>
</div>
<small class="text-muted">{{ video.duration }} mins</small>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</main>
</body>
</html>
Running this as is gives a MultiValueDictKeyError at 'q' : request.POST['search'],
Any help would be appreciated, thanks.
You should put / in front of search/index.html instead of search/index.html.
And you don't have to have the https:// you can just put // instead.

HTML printing is wrong

So I've been looking at this for over an hour and I cannot figure out what the heck is going on.
The script is printing only a ">"
It's suppose to print the full HTML and then, after the form is submitted, print "print_after"
import webapp2
class MainHandler(webapp2.RequestHandler):
def get(self):
p = Page()
if self.request.GET:
name = self.request.GET['name']
age = self.request.GET['age']
time = self.request.GET['time']
model = self.request.GET['model']
radio = self.request.GET['trade']
self.response.write(p.print_after(name, age, time, model, radio))
print name + age + time + model + radio
else:
self.response.write(p.print_one)
class Page(object):
def __init__(self):
self.page_body = '''
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="css/main.css">
<title>Audi Test Drive Request</title>
</head>
<body>
<img src="assets/custom/images/logo.png" title="logo" alt="" width="200px" height="150px"/>
<h3>It's awesome that you want to test-drive one of our vehicles</h3>
<form method="GET" action="">
<label>Name</label>
<br>
<input type="text" name="name" required>
<br>
<label>Age</label>
<br>
<input type="text" name="age" required>
<br>
<label>Time</label>
<br>
<select name="time" required>
<option value="12:00 PM">12:00 PM</option>
<option value="12:30 PM">12:30 PM</option>
<option value="1:00 PM">1:00 PM</option>
</select>
<br>
<label>Model</label>
<br>
<select name="model" required>
<option value="2008 Audi A4">2008 Audi A4</option>
<option value="2008 Audi S4">2008 Audi S4</option>
<option value="2008 Audi RS4">2008 Audi RS4</option>
</select>
<br>
<label>Are you trading in a vehicle?</label>
<br>
<input type="radio" name="trade" value="yes" required>Yes<br>
<input type="radio" name="trade" value="no" required>No<br>
<br>
<input type="submit" value="Request Test Drive">
</form>
</body>
</html>
'''
self.page_after = '''
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="css/main.css">
<title>Audi Test Drive Request</title>
</head>
<body>
<img src="assets/custom/images/logo.png" title="logo" alt="" width="200px" height="150px"/>
<h3>It's awesome that you want to test-drive one of our vehicles</h3>
</body
</html>
'''
def print_one(self):
page_content = self.page_body
page_content = page_content.format(**locals())
return page_content
def print_after(self, name, age, time, model, radio):
after_page_content = self.page_after
after_page_content = after_page_content.format(**locals())
return after_page_content
app = webapp2.WSGIApplication([
('/', MainHandler)
], debug=True)
I tested your code and rearranged it a little. I used http post for submitting the form and then it prints the form variables.
import webapp2
class HelloWebapp2(webapp2.RequestHandler):
def get(self):
self.response.write('''<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="css/main.css">
<title>Audi Test Drive Request</title>
</head>
<body>
<img src="assets/custom/images/logo.png" title="logo" alt="" width="200px" height="150px"/>
<h3>It's awesome that you want to test-drive one of our vehicles</h3>
<form method="POST" action="">
<label>Name</label>
<br>
<input type="text" name="name" required>
<br>
<label>Age</label>
<br>
<input type="text" name="age" required>
<br>
<label>Time</label>
<br>
<select name="time" required>
<option value="12:00 PM">12:00 PM</option>
<option value="12:30 PM">12:30 PM</option>
<option value="1:00 PM">1:00 PM</option>
</select>
<br>
<label>Model</label>
<br>
<select name="model" required>
<option value="2008 Audi A4">2008 Audi A4</option>
<option value="2008 Audi S4">2008 Audi S4</option>
<option value="2008 Audi RS4">2008 Audi RS4</option>
</select>
<br>
<label>Are you trading in a vehicle?</label>
<br>
<input type="radio" name="trade" value="yes" required>Yes<br>
<input type="radio" name="trade" value="no" required>No<br>
<br>
<input type="submit" value="Request Test Drive">
</form>
</body>
</html>
''')
def post(self):
if self.request.POST:
name = self.request.POST['name']
age = self.request.POST['age']
time = self.request.POST['time']
model = self.request.POST['model']
radio = self.request.POST['trade']
self.response.write(name +" " + age +" " + time +" " + model +" " + radio)
app = webapp2.WSGIApplication([
('/', HelloWebapp2),
], debug=True)
def main():
from paste import httpserver
httpserver.serve(app, host='127.0.0.1', port='8080')
if __name__ == '__main__':
main()
The above code starts a local webserver at port 8080. It might not do exactly what you want, but much is there. You can also run it in appengine.

Categories