Flask - Multi user access with OOP - python

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.

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.

response.form.get getting No Values in flask python application

I am new to flask application. I am trying to loop over input of webapp. Based on which i want to show the result on web app. Html template is fine, UDF is also fine only key_from_web is not fetching any value so result is also blank list.
Html:
<!doctype html>
<html>
<head>
<title>superman </title>
</head>
<body> Enter the Registration Number !</body>
<div class="login">
<form action="{{url_for('details')}}">
<input type="text" name="Siret Number" placeholder="siret if you are in France" required="required" />
<button type="submit" class="btn btn-primary btn-block btn-large"> Details </button>
</form>
</div>
<br>
{{ prediction_text }}
</html>
Python:
app = Flask(__name__)
#app.route('/')
def home():
return render_template("sample.html")
#app.route('/details',methods=['Get','POST'])
def details():
d = {'col1': [1,1,2], 'col2': [3, 4, 5]}
df = pd.DataFrame(data=d)
df_dict= {str(k): v.to_json(orient= 'records') for k , v in df.groupby('col1')}
# value entered on web app
key_from_web = request.form.get("Siret Number")
result = []
for key_,val_ in df_dict.items():
"""when key_ is entered it should show json output of MATCHED Key_'s val_"""
if key_ == key_from_web:
result.append(val_)
return render_template("sample.html", prediction_text = f"Company details are : {result}")
#call main fun
if __name__ == "__main__":
app.run(debug=True)
Expected Output:
If user enter 1 it should display respective value [{"col1":1,"col2":3},{"col1":1,"col2":4}]

How to run a python script like class in django?

I'm bit new with django and I'm lost, I don't know what to do. I'll explain what I want, maybe you can help me.
I want to create a web page on my site where you input your data and based on your data you get created a excel template which you download. Most basic, you input name of rows and columns and you download an excel document.
Here is what I have tried so far... I have a my_django folder and my_app folder, in my_app I'm trying to create an app to create templates.
This is my_app/views.py
from django.shortcuts import render
from django.http import HttpResponse
from .forms import TemplateForm
import xlsxwriter
from xlsxwriter import workbook
def home(request):
return render(request, 'my_app/home.html')
def create_template(request):
return render(request, 'my_app/create_template.html')
class CreateMyWebTemplate():
def create_template(doc_name, name_sheet, years, name_columns):
file = xlsxwriter.Workbook(doc_name + '_template.xlsx')
worksheet_data = file.add_worksheet()
worksheet_data.write_row(0, 1, years)
worksheet_data.write_column(1, 0, name_columns)
file.close()
return file
This is my_app/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='my-home'),
path('create-template/', views.create_template, name='my-create-template'),
]
This is my_app/forms.py
from django import forms
class CreateMyWebTemplate(forms.Form):
doc_name = forms.CharField()
name_sheet = #selectedcountry
years = #listfromweb
name_rows = #imputed column names
This is my_app/template/my_app/create_template.html
{% extends "my_app/base.html" %}
{% block content %}
<div class="create-template-box">
<form action="/">
<h1>Create your template</h1>
<div class="item">
<p>Document name</p>
<div class="name-item">
<input type="text" name="doc_name" placeholder="Input document name without spaces" />
</div>
</div>
<div class="item">
<p>Select a country for the name of sheet</p>
<select name="name_sheet">
<option value="">Country</option>
<option value="1">Russia</option>
<option value="2">Germany</option>
<option value="3">France</option>
<option value="4">Armenia</option>
<option value="5">USA</option>
</select>
</div>
</div>
<div class="item" name="years">
<p>Select a years for columns</p>
<p> Start: </p> <select name="yearpicker" id="yearpicker"></select>
<br>
<p>End: </p> <select name="yearpicker2" id="yearpicker2"></select>
</div>
<div class="item">
<p>Please input a names of rows... seperate with commas</p>
<input type="text" name="name_rows"/>
</div>
<div class="btn-block">
<button type="submit" href="#">Create and Download!</button>
</div>
</form>
</div>
<script type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js">
</script>
<script type="text/javascript">
let startYear = 1800;
let endYear = new Date().getFullYear();
for (i = endYear; i > startYear; i--)
{
$('#yearpicker, #yearpicker2').append($('<option />').val(i).html(i));
}
$('select').on('change', function(){
let arr = Array.from({length:$('#yearpicker2').val() - +$('#yearpicker').val()},(v,k)=>k + +$('#yearpicker').val())
console.log(arr);
})
</script>
{% endblock content %}
In my_django app is included in settings.py and urls.py
For your create_template view, you can handle both HTTP GET and HTTP POST methods. You can also use Django's built-in form handling to make this so much easier.
New create_template.html
...
<form action="create_template" method="GET">
{% csrf_token %}
<h1>Create your template</h1>
<div class="item">
<table>
{{ form.as_table }}
</table>
</div>
<div class="btn-block">
<input type="button" type="submit" value="Create and Download!"/>
</div>
</form>
...
New content of views.py
from django.forms import Forn, CharField, ChoiceField, IntegerField,
...
class TemplateForm(Form):
name = CharField(label='Doc name')
choices=[('1', 'Russia'), ('2', 'Germany'), ('3', 'France'),
('4', 'Armenia'), ('5', 'USA')]
country = ChoiceField(label='name_sheet', initial='5', choices=choices)
choices = []
for year in range (2000, 2050):
choices.append( (year, year) )
year1 = ChoiceField(label='Starting Year', initial=2021, choices=choices)
year2 = ChoiceField(label='Ending Year', initial=2022, choices=choices)
columns = CharField(label='Column names')
def create_template(request):
if request.method == 'GET':
form = TemplateForm()
return render(request, 'my_app/create_template.html' form=form)
else:
form = TemplateForm(request.POST)
<use form inputs as needed>
...

How to resolve reverse match error in django

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 %}

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