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.
Related
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>
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.
I'm new to Django and I cannot understand why this error is popping up:
django.urls.exceptions.NoReverseMatch: Reverse for 'updater' with no arguments not found. 1 pattern(s) tried: ['update/(?P<updating>[0-9]+)$']
[26/Jul/2020 19:05:05] "GET /update/2 HTTP/1.1" 500 127513
my urls:
urlpatterns=[
path('update/<int:updating>',views.update,name='updater'),
]
the html page:
<!DOCTYPE html>
<html lang="en">
<head>
{% load static %}
<title>NEW PRODUCT</title>
</head>
<body>
<div class="bg-contact2" style="background-image: url('images/bg-01.jpg');">
<div class="container-contact2">
<div class="wrap-contact2">
<form class="contact2-form validate-form" method="post" action="{%url 'updater' %}" enctype="multipart/form-data">
{% csrf_token %}
<span class="contact2-form-title">
Provide Product details Below
</span>
<div class="wrap-input2 validate-input" data-validate="type is required">
<input class="input2" type="text" name="type" value="{{details.product_type}}">
<span class="focus-input2" data-placeholder="PRODUCT-TYPE"></span>
</div>
<div class="wrap-input2 validate-input" data-validate = "Name is required">
<input class="input2" type="text" name="name" value="{{details.product_name}}">
<span class="focus-input2" data-placeholder="PRODUCT NAME"></span>
</div>
<div class="wrap-input2 validate-input" data-validate = "description is required">
<textarea class="input2" name="description">{{details.product_description}}</textarea>
<span class="focus-input2" data-placeholder="PRODUCT DESCRIPTION"></span>
</div>
<div class="wrap-input2 validate-input" data-validate = "Price is required">
<input class="input2" type="number" name="price" value="{{details.product_price}}">
<span class="focus-input2" data-placeholder="PRICE"></span>
</div>
<div class="wrap-input2 validate-input" data-validate = "Picture is required">
<label >product sample picture</label>
<input class="input2" type="file" name="picture">
<span class="focus-input2" data-placeholder=""></span>
</div>
<div class="container-contact2-form-btn">
<div class="wrap-contact2-form-btn">
<div class="contact2-form-bgbtn"></div>
<button class="contact2-form-btn">
Update Product Listing
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</body>
</html>
my views:
def update (request,updating):
if request.method=='POST':
product_details=product_info.objects.get(id=updating)
product_details.product_type=request.POST.get('type')
product_details.product_name=request.POST.get('name')
product_details.product_description=request.POST.get('description')
product_details.product_price=request.POST.get('price')
if (len(request.FILES) != 0):
image = request.FILES['picture']
product_details.product_pic = image
product_details.save()
alldetails = product_info.objects.all()
return render(request, 'adminside/editingpage.html', {'editing_details': alldetails})
else:
product_details = product_info.objects.get(id=updating)
return render(request,'adminside/updating.html',{'details':product_details})
def update (request,updating) :
if request.method=='POST' :
product_details=product_info.objects.get(id=updating)
product_details.product_type=request.POST.get('type')
product_details.product_name=request.POST.get('name')
product_details.product_description=request.POST.get('description')
product_details.product_price=request.POST.get('price')
if (len(request.FILES) != 0):
image = request.FILES['picture']
product_details.product_pic = image
product_details.save()
alldetails = product_info.objects.all()
return render(request, 'adminside/editingpage.html', {'editing_details': alldetails})
else:
product_details = product_info.objects.get(id=updating)
return render(request,'adminside/updating.html',{'details':product_details})
def update (request,updating):
if request.method=='POST':
product_details=product_info.objects.get(id=updating)
product_details.product_type=request.POST.get('type')
product_details.product_name=request.POST.get('name')
product_details.product_description=request.POST.get('description')
product_details.product_price=request.POST.get('price')
if (len(request.FILES) != 0):
image = request.FILES['picture']
product_details.product_pic = image
product_details.save()
alldetails = product_info.objects.all()
return render(request, 'adminside/editingpage.html', {'editing_details': alldetails})
else:
product_details = product_info.objects.get(id=updating)
return render(request,'adminside/updating.html',{'details':product_details})
I think it has something to do with passing the id of the product in the url, but I'm not sure about how to resolve it.
you have not put any argument in the url you have to put argument in the form action for updating like this
<form class="contact2-form validate-form" method="post" action="{%url 'updater' updating='ANYVALUE' %}" enctype="multipart/form-data">
because you haven't specify any value your url is not matching
This urlpattern update/ takes an int route parameter
path('update/<int:updating>',views.update,name='updater'),
In your template, you're trying to reverse updater with no included argument. So it's trying to reverse to a urlpattern of update/ which it can't find because you only have a path for update/<int:updating>
{%url 'updater' %}
You will need to change it to the following as you gave the context object the name details and you can access
{%url 'updater' details.id %}
I created an app with flask but I'm having a problem with multi-user access bcs of the global variables. Whenever I run the script (it might take minutes) and someone else is trying to access the page and run a script there too a collision appear and data by both users mix.
I truly understand that I should be using OOP in this case, but I'm not able to replicate the OOP usage for this app (yes, I'm an OOP beginner ). Can someone please give me a hint or a little bit of code about OOP for this case?
Much appreciated.
Python:
from flask import Flask, render_template, url_for, request, redirect, Response
from datetime import datetime
import time
import pandas as pd
import re
import os
app = Flask(__name__)
#app.route('/', methods=['POST', 'GET'])
def index():
if request.method == 'POST':
start_date = request.form["Start_date"]
end_date = request.form["End_date"]
dates = pd.period_range(start=start_date, end=end_date, freq='D')
global s_date
global f_date
s_date = dates[0]
f_date = dates[-1]
print(s_date, f_date)
query = request.form["query"].strip()
splitted = query.split("\r\n")
global fiii
fiii = pd.DataFrame()
for x in splitted:
print(x)
for date in dates:
print(date)
directory = '/home/USER/Parquets/{}/{:02d}/{:02d}/'.format(date.year, date.month, date.day)
for filename in os.listdir(directory):
if filename.endswith(".parquet"):
df = pd.read_parquet(directory)
df.set_index("query", inplace=True)
if request.form.get('lowercase') == "on":
df.index = df.index.str.casefold()
if request.form.get('sensitive') == "on":
fiii = fiii.append(df.filter(regex=re.compile(x), axis=0))
else:
fiii = fiii.append(df.filter(regex=re.compile(x, re.IGNORECASE), axis=0))
fiii = fiii.groupby(['query'])["total"].sum().sort_values(ascending=False)
if request.form.get('csv') == "on":
return redirect("/getCSV")
else:
pass
# return render_template("index.html")
return fiii.to_frame().to_html(table_id="table")
else:
return render_template("index.html")
#app.route("/getCSV")
def getPlotCSV():
return Response(
fiii.to_csv(encoding="UTF-8", sep="\t", header=True),
mimetype="text/csv",
headers={"Content-disposition":
f"attachment; filename={s_date}-{f_date}.csv"})
if __name__ == "__main__":
app.run(debug=True,port=4444)
HTML:
<html lang="en"><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mate rialize/1.0.0/css/materialize.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js /materialize.min.js"></script>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel ="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<form class="col s6 offset-s3" action="/" method="POST">
<div class="valign-wrapper col s12">
<h3 class="col s6">Query master</h3>
<div class="right-align input-field col s6">
<button class="btn btn-large btn-floating waves- effect waves-light" type="submit" name="action">
<i class="material-icons right">send</i>
</button>
</div>
</div>
<div class="input-field col s12">
<input type="text" id="date-start" class="datepicker " name="Start_date">
<label for="date-start">Start Date</label>
</div>
<div class="input-field col s12">
<input type="text" id="date-end" class="datepicker" name="End_date">
<label for="date-end">End Date</label>
</div>
<label class="input-field col s12">
<input type="checkbox" name="lowercase" />
<span>Lowercase queries</span>
</label>
<label class="input-field col s12">
<input type="checkbox" name="sensitive" />
<span>Case sensitive</span>
</label>
<label class="input-field col s12">
<input type="checkbox" name="csv" />
<span>CSV export (Funkční pouze csv export)</span>
</label>
<div class="input-field col s12">
<textarea id="textarea1" name="query" class="materia lize-textarea"></textarea>
<label for="textarea1">Queries (RegEx supported)</la bel>
</div>
</form>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.datepicker');
var instances = M.Datepicker.init(elems, {
format: 'm/d/yyyy',
});
});
</script>
</div>
</body>
</html>
Your problem has absolutely nothing to do with OO - it's only the result of using gobal variables.
Your flask server process will serve all incoming requests, one after the other. So what happens in a multi-user scenario is:
1/ user A posts to index. This assigns values to your globals s_date, f_date and fills.
2/ user A is redirected to getCSV
3/ in the meantime, user B posts to index. This rebinds your globals s_date, f_date and fills to new values
4/ user A's browser has followed the redirection, and renders the fill of user B.
The solution is quite simple: do NOT use global state for per-user data persistance - you want either a user session for short-lived session data and/or a RDBMS for long-lived user data.
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.