I have simple html template with link, that starts script, in views that retrieves data to the page,in views file I have two functions: render function def output(request):(it retrieves data to the page) and another function def summoner(): that makes postgres quires in cycle and appends results to the list. Separately each of them work fine, but I have to call second function from render function and retrieve the data to the page, but now when I do that all I am getting is empty list.
enter image description here
template:
<html>
<head>
<title>
Python script
</title>
</head>
<body>
Execute Script <hr>
{% if data %}
{{ data }}
{% endif %}
</body>
</html>
views:
from django.shortcuts import render
import pandas as pd
import psycopg2
import os, glob
conn = psycopg2.connect(host='127.0.0.1', database='db',
user='user', password='pass')
cur = conn.cursor()
def insert_data_as_is(file_name):
cur.execute('truncate table test_inv.start_tbl')
with open(file_name, 'r') as file:
cur.execute("insert into test_inv.start_tbl values {0}".format(file.read()))
conn.commit()
def insert_data_to_be(file_name):
cur.execute('truncate table test_inv.res_calc_ratios_t')
with open(file_name, 'r') as file:
cur.execute('insert into test_inv.res_calc_ratios_t (test_no, test_name, hcode_id, '
'hcode_name, hcode_'
'unit_name,'
' org_id, dor_kod, duch_id, nod_id, date_type_id, metric_type_id, cargo_type_id, val_type_id,'
' unit_id, dt, value, ss, dir_id, kato_id, vids_id) values {0}'.format(file.read()))
conn.commit()
path_start = 'files/csv_s/as_is/'
start_list = []
path_finish = 'files/csv_s/to_be'
finish_list = []
for infile in glob.glob(os.path.join(path_start, '*.*')):
start_list.append(infile)
for infile in glob.glob(os.path.join(path_finish, '*.*')):
finish_list.append(infile)
def summoner():
fun_sql_set = []
fun_query = """select * from test_inv.test_ratios('1','15')"""
for i in range(len(finish_list)):
insert_data_as_is(start_list[i])
insert_data_to_be(finish_list[i])
results = pd.read_sql_query(fun_query, conn)
fun_sql_set.append(results)
return fun_sql_set
def index(request):
return render(request,'calculus/index.html')
def output(request):
data = summoner()
print(data)
return render(request,'calculus/index.html',{'data':data})
The answer is creating absolute file path:
cur_dir = os.path.dirname(os.path.abspath(__file__))
path_start = '{}/static/csv_s/as_is/'.format(cur_dir)
path_finish = '{}/static/csv_s/to_be/'.format(cur_dir)
Related
This works but..
views.py
from django.http import HttpResponse
from django.db import connection
def query():
with connection.cursor() as cursor:
cursor.execute('SELECT some, stuff FROM here;')
row = cursor.fetchall()
return row
def index(request):
return HttpResponse(query())
What if I want to get a filtered response that is restricted to a user or group from the admin?
For example, if the user is in the BAIT group they could filter results WHERE email LIKE 'bob#bait.com';
I did it like this...
/opt/my_project/my_app/templates/my_app/generate_html.html
<html>
<h1>Generate HTML</h1>
<form method="POST" action="">
{% csrf_token %}
{{ form }}
<button type="submit">Submit Query</button>
</form>
</html>
/opt/my_project/my_project/settings.py
'DIRS': ['/opt/my_project/my_app/templates/my_app'],
/opt/my_project/my_app/urls.py
path('generate_html/', generate_html, name = "generate_html"),
/opt/my_project/my_app/forms.py
from django import forms
class InputForm(forms.Form):
email = forms.EmailField(max_length = 100)
/opt/my_project/my_app/views.py
def query(email):
with connection.cursor() as cursor:
query = '''SELECT some, stuff
FROM here
WHERE email = %s
ORDER BY stuff;
'''
values = (email,)
cursor.execute(query, values)
select = cursor.fetchall()
return select
def generate_html(request):
if request.method == 'POST':
email = request.POST.get('email', None)
try:
html = '<!DOCTYPE html><html><body>'
for row in query(email):
some, stuff = row
html += 'Row: ' + some + ' ' + stuff + '<br>'
html += '<br><br>' + 'Search Again!' + '</body></html>'
return HttpResponse(html)
except Exception as e:
return HttpResponse(str(e))
else:
context ={}
context['form']= InputForm()
return render(request, "generate_html.html", context)
Im doing the cs50 web course and working in Django.
I need to select md files based on the keyword that the user searches. If the query does not match the name of an the files, the user should instead be taken to a search results page that displays a list of all files that have the query as a substring. For example, if the search query were Py, then Python should appear in the search results assuming such file exists.
Problem is im not sure how. Also we arent using sql.
Here is util.py, code given by course that we are told we dont need to touch:
import re
from django.core.files.base import ContentFile
from django.core.files.storage import default_storage
def list_entries():
"""
Returns a list of all names of encyclopedia entries.
"""
_, filenames = default_storage.listdir("entries")
return list(sorted(re.sub(r"\.md$", "", filename)
for filename in filenames if filename.endswith(".md")))
def save_entry(title, content):
"""
Saves an encyclopedia entry, given its title and Markdown
content. If an existing entry with the same title already exists,
it is replaced.
"""
filename = f"entries/{title}.md"
if default_storage.exists(filename):
default_storage.delete(filename)
default_storage.save(filename, ContentFile(content))
def get_entry(title):
"""
Retrieves an encyclopedia entry by its title. If no such
entry exists, the function returns None.
"""
try:
f = default_storage.open(f"entries/{title}.md")
return f.read().decode("utf-8")
except FileNotFoundError:
return None
Here are my views function:
def entry(request, title): #based on the url it shows a md file
try:
content = markdown2.markdown(util.get_entry(title))
except:
return HttpResponseNotFound("Page not found")
return render(request, "encyclopedia/entry.html", {
"entry": content, "title": title.capitalize()
})
def search(request):
keyword = request.GET.get('q')
result = util.get_entry(keyword)
if result: #if the keyword matches a title, return that result
content = markdown2.markdown(util.get_entry(result))
return redirect('entry', result)
else: #here i should return results that match the substring query
#stuck
results = util.get_entry('%keyword%')
return render(request, "encyclopedia/results.html", {
"results": results
})
Search bar:
<form method="get" action="{% url 'search' %}">
{% csrf_token %}
<input type="text" name="q" placeholder="Search Encyclopedia">
</form>
You can achieve this by using indexing in Python.
Here is how I did it.
list = ["Python", "CSS"]
q = "Py"
for i in list:
for j in range(3):
result = str(i[0:j])
if result == q:
print("One entry found: ", i)
Output:
One entry found: Python
I am developing program where I can upload excel invoice .xlsx file using Flask and then store that file to mysql when user click submit button. There are total three files involved. getFile.py which is Flask to upload file using index.html. exlTomySQL.py store data to mysql from file received by index.html. I am new to Flask and don't know how to process data after clicking submit button on index.html to process .xlsx file and return response for user.
getFile.py
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
fileDetails = request.form
myFile = fileDetails['myfile']
return myFile
return render_template('index.html')
if __name__ == "__main__":
app.run(debug=True)
Index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Page</title>
</head>
<body>
<form method="POST" action="">
<label for="myfile">Select a file:</label>
<br>
<input type="file" id="myfile" name="myfile">
<br>
<input type="submit">
</form>
</body>
</html>
exlToSQL.py
import openpyxl
import math
import datetime
import mysql.connector
wb = openpyxl.load_workbook('myFile')
sheet = wb.active
# count rows of data for column 2 as it represent description
def countRows():
count = 0
for i in range(1, 100, 1):
if sheet.cell(row=i, column=2).value != None:
count = i
return count
# list each row description, (not counting quantity), gst amount and last column(total excluding GST)
def readRows():
description = []
# quantity = []
amount = []
gstAmount = []
for i in range(3, countRows() + 1, 1):
description.append(sheet.cell(row=i, column=2).value)
# quantity.append(sheet.cell(row=i, column=5).value)
gstAmount.append(sheet.cell(row=i, column=10).value)
amount.append(sheet.cell(row=i, column=11).value)
uperCaseDescription = [desc.upper()
for desc in description]
return uperCaseDescription, gstAmount, amount
# count all list totals for GST and Amount
def countTotals():
uperCaseDescription, gstAmount, amount = readRows()
totalGST = round(sum(gstAmount), 2)
subTotalAmount = round(sum(amount), 2)
totalAmountOfInvoice = round((totalGST + subTotalAmount), 2)
return totalGST, subTotalAmount, totalAmountOfInvoice
# get static data of invoice e.g. invoice number,
# invoice date, sub total, total gst, total inc gst
print(countRows())
print(countTotals())
invoice_number = sheet.cell(row=1, column=1).value
print("Invoice Number:", invoice_number)
invoice_date = sheet.cell(row=1, column=2).value
print("Invoice Date:", invoice_date)
sun_offset = (invoice_date.weekday() - 6) % 7
weekEnd = invoice_date - datetime.timedelta(days=sun_offset)
print("Week End Date:", weekEnd)
print(readRows())
# merge all list into tuple
def mergeList():
uperCaseDescription, gstAmount, amount = readRows()
mergeTuple = tuple(zip(uperCaseDescription, gstAmount, amount))
return mergeTuple
# MySql connection and transfer data to mysql
mydb = mysql.connector.connect(
host="localhost",
user="root",
password="Vrishab2145",
database="testdbOne"
)
# creating database_cursor to perform SQL operation
mycursor = mydb.cursor()
sqlFormula = "INSERT INTO invoice (description, gstAmount, totalExGst) VALUES (%s,%s,%s)"
mycursor.executemany(sqlFormula, mergeList())
mydb.commit()
You can save the file being uploaded by making some changes in your code as shown below.
Once you have saved the file, you can deal with the file processing to store the data to MySQL. You can also delete the file previously saved once the processing is done.
getFile.py
from flask import Flask, render_template, request
import os
app = Flask(__name__)
app.config["UPLOADS"] = "C:/FlaskSandbox/uploads" # path where uploads are saved. Can also be UNIX path
#app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
userfile = request.files['myfile']
userfile.save(os.path.join(app.config["UPLOADS"], userfile.filename))
print('File Saved!')
# call your file processing functions below
return render_template('index.html')
if __name__ == "__main__":
app.run(debug=True)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Page</title>
</head>
<body>
<form method="POST" action="" enctype=multipart/form-data>
<label for="myfile">Select a file:</label>
<br>
<input type="file" id="myfile" name="myfile">
<br>
<input type="submit">
</form>
</body>
</html>
Bellow Code working perfectly fine. After spending so many days finally worked out.
from flask import Flask, render_template, request
from werkzeug.utils import secure_filename
import os
import openpyxl
import math
import datetime
import mysql.connector
app = Flask(__name__)
# path where uploads are saved. Can also be UNIX path
app.config["UPLOADS"] = "/Users/vrishabpatel/Desktop/PythonPrep/FlaskApp/uploads"
#app.route('/', methods=['GET', 'POST'])
def index():
mydb = mysql.connector.connect(
host="localhost",
user="root",
password="Vrishab2145",
database="testdbOne"
)
if request.method == 'POST':
userfile = request.files['myfile']
userfile.save(os.path.join(app.config["UPLOADS"], userfile.filename))
print('File Saved!')
# call your file processing functions below
wb = openpyxl.load_workbook(userfile)
sheet = wb.active
mycursor = mydb.cursor()
sqlFormula = "INSERT INTO invoice (description, gstAmount, totalExGst) VALUES (%s,%s,%s)"
mycursor.executemany(sqlFormula, mergeList(sheet))
mycursor.close()
mydb.commit()
return render_template('index.html')
# creating database_cursor to perform SQL operation
# countRows()
# readRows()
# countTotals()
def countRows(sheet):
count = 0
for i in range(1, 100, 1):
if sheet.cell(row=i, column=2).value != None:
count = i
return count
def readRows(sheet):
description = []
# quantity = []
amount = []
gstAmount = []
for i in range(3, countRows(sheet) + 1, 1):
description.append(sheet.cell(row=i, column=2).value)
# quantity.append(sheet.cell(row=i, column=5).value)
gstAmount.append(sheet.cell(row=i, column=10).value)
amount.append(sheet.cell(row=i, column=11).value)
uperCaseDescription = [desc.upper()
for desc in description]
return uperCaseDescription, gstAmount, amount
def countTotals(sheet):
uperCaseDescription, gstAmount, amount = readRows(sheet)
totalGST = round(sum(gstAmount), 2)
subTotalAmount = round(sum(amount), 2)
totalAmountOfInvoice = round((totalGST + subTotalAmount), 2)
return totalGST, subTotalAmount, totalAmountOfInvoice
def mergeList(sheet):
uperCaseDescription, gstAmount, amount = readRows(sheet)
mergeTuple = tuple(zip(uperCaseDescription, gstAmount, amount))
return mergeTuple
if __name__ == "__main__":
app.run(debug=True)
Please Before Dislike this Question ask me what you don't understand Hello Guys i have data generation program which will do lots of computation so i cannot paste my whole program here so only talking about my program All the computation of the program starts with reading the file so when i'm selecting multiple CSV file in web page in "choose file" option i need to validate the columns numbers(should be same) of the all csv file and columns headers name should also match.. program i have written is like this:
from flask import Flask, render_template
import os
import csv
import pandas as pd
import numpy as np
app = Flask(__name__)
APP_ROOT = os.path.dirname(os.path.abspath(__file__))
#app.route("/")
def index():
print("Loading the root file")
return render_template("upload.html")
#app.route("/upload", methods=['POST'])
def upload():
target = os.path.join(APP_ROOT, 'input/')
print("target-",target)
if not os.path.isdir(target):
os.mkdir(target)
for file in request.files.getlist("source_fileName"):
print("file-",file)
filename = file.filename
print("filename-",filename)
destination = "/".join([target, filename])
print("destination-",destination)
file.save(destination)
print("file>",file)
global tempFile
tempFile = destination
print("tempFile - " + tempFile)
return redirect("/compute", )
def compute():
readerForRowCheck = pd.read_csv(tempFile)
for row in readerForRowCheck:
if (len(row) != 8):
return render_template("Incomplete.html")
headerColumn1 = row[0];
headerColumn2 = row[1];
headerColumn3 = row[2];
headerColumn4 = row[3];
headerColumn5 = row[4];
headerColumn6 = row[5];
headerColumn7 = row[6];
headerColumn8 = row[7];
if (headerColumn1 != "Asset_Id") or (headerColumn2 != "Asset Family") \
or (headerColumn3 != "Asset Name") or (headerColumn4 != "Location")or (headerColumn5 != "Asset Component") \
or (headerColumn6 != "Keywords") or (headerColumn7 != "Conditions") or (headerColumn8 != "Parts") :
return render_template("incomplete.html")
.....................................so on to then it will go to perform other task
HTML program:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title> upload </title>
</head>
<body>
<div class="container">
<h1>Large Data Generation</h1>
<form id = "upload-form" action="{{ url_for('upload') }}" method="POST" enctype="multipart/form-data">
<div id="file-selector">
<p>
<strong>Source File: </strong>
<input id="source_fileName" type="file" name="source_fileName" accept="csv/*" multiple />
</p>
</div>
<input type="submit" value="Generate Data" id="upload-button" >
</form>
</div>
</body>
Note:**I have only given lines of code which important otherwise its contain lots of code **Here i'm getting that how should i validate the csv file on the columns numbers and name should be same i know my validation for reading csv file is not correct that why i'm here please Help me.....thanks
I You are having multiple files then you need to create instance of dataframe for each file
Upload function will look like this:
def upload():
target = os.path.join(APP_ROOT, 'input/')
print("target-",target)
if not os.path.isdir(target):
os.mkdir(target)
abs_path_files=[]
for file in request.files.getlist("source_fileName"):
print("file-",file)
filename = file.filename
print("filename-",filename)
destination = "/".join([target, filename])
print("destination-",destination)
file.save(destination)
print("file>",file)
tempFile = os.path.abspath(destination)
abs_path_files.append(tempfile)
print("tempFile - " + tempFile)
return redirect(url_for("compute", files_list=abs_path_files))
Compute Function will look like this:
def compute(files_list):
dataFrames=[]
for f in files_list:
dataFrame=pd.read_csv(f)
dataFrames.append(dataFrame)
col_in_files = set([",".join(list(f.column.values)) for f in dataFrames])
if len(col_in_files)==1:
#then process your data here
I am trying to get the fileadmin to get multiple files uploaded but can't figure out how to do that.
Currently in the below reference I can only upload one file at a time.
https://github.com/flask-admin/flask-admin/blob/master/examples/file/app.py
(New Link to to file: https://github.com/mrjoes/flask-admin/blob/master/examples/file/app.py )
I tried updating the html template to have multiple="" but that didn't helped to upload multiple files.
Further looking into this I think this html file needs to have multiple=""
Python27\Lib\site-packages\flask_admin\templates\bootstrap3\adminC:\Python27\Lib\site-packages\flask_admin\templates\bootstrap3\admin\lib.html
Although I am not sure where/how to add this tag without actually overwriting the source file.
You should custom ImageUploadInput and ImageUploadField as follows.
import ast
from PIL import Image
from wtforms.widgets import html_params, HTMLString
from wtforms.utils import unset_value
from flask_admin.helpers import get_url
from flask_admin.form.upload import ImageUploadField
from flask_admin._compat import string_types, urljoin
class MultipleImageUploadInput(object):
empty_template = "<input %(file)s multiple>"
# display multiple images in edit view of flask-admin
data_template = ("<div class='image-thumbnail'>"
" %(images)s"
"</div>"
"<input %(file)s multiple>")
def __call__(self, field, **kwargs):
kwargs.setdefault("id", field.id)
kwargs.setdefault("name", field.name)
args = {
"file": html_params(type="file", **kwargs),
}
if field.data and isinstance(field.data, string_types):
attributes = self.get_attributes(field)
args["images"] = " ".join(["<img src='{}' /><input type='checkbox' name='{}-delete'>Delete</input>"
.format(src, filename) for src, filename in attributes])
template = self.data_template
else:
template = self.empty_template
return HTMLString(template % args)
def get_attributes(self, field):
for item in ast.literal_eval(field.data):
filename = item
if field.thumbnail_size:
filename = field.thumbnail_size(filename)
if field.url_relative_path:
filename = urljoin(field.url_relative_path, filename)
yield get_url(field.endpoint, filename=filename), item
class MultipleImageUploadField(ImageUploadField):
widget = MultipleImageUploadInput()
def process(self, formdata, data=unset_value):
self.formdata = formdata # get the formdata to delete images
return super(MultipleImageUploadField, self).process(formdata, data)
def process_formdata(self, valuelist):
self.data = list()
for value in valuelist:
if self._is_uploaded_file(value):
self.data.append(value)
def populate_obj(self, obj, name):
field = getattr(obj, name, None)
if field:
filenames = ast.literal_eval(field)
for filename in filenames[:]:
if filename + "-delete" in self.formdata:
self._delete_file(filename)
filenames.remove(filename)
else:
filenames = list()
for data in self.data:
if self._is_uploaded_file(data):
self.image = Image.open(data)
filename = self.generate_name(obj, data)
filename = self._save_file(data, filename)
data.filename = filename
filenames.append(filename)
setattr(obj, name, str(filenames))
After that, You can use them as image upload example in flask-admin
class ModelHasMultipleImages(db.Model):
id = db.Column(db.Integer(), primary_key=1)
# len of str representation of filename lists may exceed the len of field
image = db.Column(db.String(128))
class ModelViewHasMultipleImages(ModelView):
def _list_thumbnail(view, context, model, name):
if not model.image:
return ''
def gen_img(filename):
return '<img src="{}">'.format(url_for('static',
filename="images/custom/" + form.thumbgen_filename(image)))
return Markup("<br />".join([gen_img(image) for image in ast.literal_eval(model.image)]))
column_formatters = {'image': _list_thumbnail}
form_extra_fields = {'image': MultipleImageUploadField("Images",
base_path="app/static/images/custom",
url_relative_path="images/custom/",
thumbnail_size=(400, 300, 1))}
The image filed of ModelHasMultipleImages store the str represent of filename list.
Dropzone is the best way to do this
Download with
pip install flask flask-uploads flask-dropzone
The Python app.py should look somthhing like this
# app.py
from flask import Flask, render_template
from flask_dropzone import Dropzone
from flask_uploads import UploadSet, configure_uploads, IMAGES, patch_request_class
import os
app = Flask(__name__)
dropzone = Dropzone(app)
# Dropzone settings
app.config['DROPZONE_UPLOAD_MULTIPLE'] = True
app.config['DROPZONE_ALLOWED_FILE_CUSTOM'] = True
app.config['DROPZONE_ALLOWED_FILE_TYPE'] = 'image/*'
app.config['DROPZONE_REDIRECT_VIEW'] = 'results'
# Uploads settings
app.config['UPLOADED_PHOTOS_DEST'] = os.getcwd() + '/uploads'
photos = UploadSet('photos', IMAGES)
configure_uploads(app, photos)
patch_request_class(app) # set maximum file size, default is 16MB
#app.route('/')
def index():
return render_template('index.html')
#app.route('/results')
def results():
return render_template('results.html')
And result.html looks as follows
# templates/results.html
<h1>Hello Results Page!</h1>
Back<p>
<ul>
{% for file_url in file_urls %}
<li><img style="height: 150px" src="{{ file_url }}"></li>
{% endfor %}
</ul>
index.html looks something like this
# templates/index.html
<!DOCTYPE html>
<html>
<head>
<title>Flask App</title>
{{ dropzone.load() }}
{{ dropzone.style('border: 2px dashed #0087F7; margin: 10%; min-height: 400px;') }}
</head>
<body>
<h1>Hello from Flask!</h1>
{{ dropzone.create(action_view='index') }}
</body>
</html>