I have my website with thwo hrefs and under this hrefs i have my flask function download_file(). It's working but now I add on my function in flask a parameter. So now I want to run something like that download_file(1) when someone clicked on first href and download_file(2) when someone clicked on href2
<h2>Download a file </h2>
<p>
Download1
Download2
</p>
############ FLASK CODE
from flask import Flask, send_file, render_template
app = Flask(__name__)
#app.route('/')
def download():
return render_template('indexdownload.html')
#app.route('/download')
def download_file(number):
p = "test"
if number == 1:
p = "1.txt"
elif number == 2:
p = "2.txt"
return send_file(p, as_attachment=True)
app.run()
I try different ways but I always get some syntax errors because I don't know hot to do that.
An anchor with an href attribute sends a GET request.
There are several alternative ways to send data within a GET request.
Variable Rule
One way to pass data within a URL is to use variable rules. The values are embedded within the path, extracted server-side, and passed to the endpoint as arguments.
#app.route('/download/<int:num>')
def download(num):
# ...
URL Parameter
An alternative is to pass it as a URL parameter. In this case, the data must be requested within the endpoint and are not necessarily available.
The respective parameter is queried using the name of the object request.args. It is possible to define a default value and optionally to automatically convert the value by specifying a type.
#app.route('/download')
def download():
num = request.args.get('num', 0, type=int)
# ...
In both cases you can pass the value to the jinja2 statement url_for to form the url.
url_for('download', num=1)
Based on the code within the request and the intended use, I would suggest the first variant. So you are assuming that a value is specified. You can put your filename together and deliver the file.
Incidentally, you can also pass an entire file name within the URL.
#app.route('/download/<path:filename>')
def download(filename):
# ...
Download
Related
For web2py there are generic views e.g. for JSON.
I could not find a sample.
When looking at the web2py manual 10.1.2 and 10.1.6, its written:
'.. define a "generic.csv" file, but one would have to specify the name of the object to be serialized ("animals" in the example)'
Looking at the generic pdf view
{{
import os
from gluon.contrib.generics import pdf_from_html
filename = '%s/%s.html' % (request.controller,request.function)
if os.path.exists(os.path.join(request.folder,'views',filename)):
html=response.render(filename)
else:
html=BODY(BEAUTIFY(response._vars))
pass
=pdf_from_html(html)
}}
and also the specified csv (Manual charpter 10.1.6):
{{
import cStringIO
stream=cStringIO.StringIO() animals.export_to_csv_file(stream)
response.headers['Content-Type']='application/vnd.ms-excel'
response.write(stream.getvalue(), escape=False)
}}
Massimo is writing: 'web2py does not provide a "generic.csv";'
He is not fully against it but..
So lets try to get it and deactivate when necessary.
The generic view should look similar to (the non working)
(well, this we better call pseudocode as it is not working):
{{
import os
from gluon.contrib.generics export export_to_csv_file(stream)
filename = '%s/%s' % (request.controller,request.function)
if os.path.exists(os.path.join(request.folder,'views',filename)):
csv=response.render(filename)
else:
csv=BODY(BEAUTIFY(response._vars))
pass
= export_to_csv_file(stream)
}}
Whats wrong?
Or is there a sample?
Is there a reson not to have a generic csv?
{{
import os
from gluon.contrib.generics export export_to_csv_file(stream)
filename = '%s/%s' % (request.controller,request.function)
if os.path.exists(os.path.join(request.folder,'views',filename)):
csv=response.render(filename)
else:
csv=BODY(BEAUTIFY(response._vars))
pass
= export_to_csv_file(stream)
}}
Adapting the generic.pdf code so literally as above would not work for CSV output, as the generic.pdf code is first executing the standard HTML template and then simply converting the generated HTML to a PDF. This approach does not make sense for CSV, as CSV requires data of a particular structure.
As stated in the documentation:
Notice that one could also define a "generic.csv" file, but one would
have to specify the name of the object to be serialized ("animals" in
the example). This is why we do not provide a "generic.csv" file.
The execution of a view is triggered by a controller action returning a dictionary. The keys of the dictionary become available as variables in the view execution environment (the entire dictionary is also available as response._vars). If you want to create a generic.csv view, you therefore need to establish some conventions about what variables are in the returned dictionary as well as the possible structure(s) of the returned data.
For example, the controller could return something like dict(data=mydata). The code in generic.csv would then access the data variable and could convert it to CSV. In that case, there would have to be some convention about the structure of data -- perhaps it could be required to be a list of dictionaries or a DAL Rows object (or optionally either one).
Another possible convention is for the controller to return something like dict(columns=mycolumns, rows=myrows), where columns is a list of column names and rows is a list of lists containing the data for each row.
The point is, there is no universal convention for what the controller might return and how that can be converted into CSV, so you first need to decide on some conventions and then write generic.csv accordingly.
For example, here is a very simple generic.csv that would work only if the controller returns dict(rows=myrows), where myrows is a DAL Rows object:
{{
import cStringIO
stream=cStringIO.StringIO() rows.export_to_csv_file(stream)
response.headers['Content-Type']='application/vnd.ms-excel'
response.write(stream.getvalue(), escape=False)
}}
I tried:
# Sample from Web2Py manual 10.1.1 Page 464
def count():
session.counter = (session.counter or 0) + 1
return dict(counter=session.counter, now = request.now)
#and my own creation from a SQL table (if possible used for json and csv):
def csv_rt_bat_c_x():
battdat = db().select(db.csv_rt_bat_c.rec_time, db.csv_rt_bat_c.cellnr,
db.csv_rt_bat_c.volt_act, db.csv_rt_bat_c.id).as_list()
return dict(battdat=battdat)
Bot times I get an error when trying csv. It works for /default/count.json but not for /default/count.csv
I suppose the requirement:
dict(rows=myrows)
"where myrows is a DAL Rows object" is not met.
I am new to django and python. I have created a django web application, I also have a python script which I have to run at the backend of the web application in real-time(Like it should always check for new updates and tell the web about new responses from the API by generating notifications). I am using an IBM-Qradar API from which I have to display the data on the web application.
I have two problems
1) Is there any way I can use the below python code with my django project just like I described above?
2) and use the API response which is in json format to store the data into MySQL database directly from response variable.
I could Only find ways to store data into the database by using forms, which is not required for my project.
import json
import os
import sys
import importlib
sys.path.append(os.path.realpath('../modules'))
client_module = importlib.import_module('RestApiClient')
SampleUtilities = importlib.import_module('SampleUtilities')
def main():
# First we have to create our client
client = client_module.RestApiClient(version='9.0')
# -------------------------------------------------------------------------
# Basic 'GET'
# In this example we'll be using the GET endpoint of siem/offenses without
# any parameters. This will print absolutely everything it can find, every
# parameter of every offense.
# Send in the request
SampleUtilities.pretty_print_request(client, 'siem/offenses', 'GET')
response = client.call_api('siem/offenses', 'GET')
# Check if the success code was returned to ensure the call to the API was
# successful.
if (response.code != 200):
print('Failed to retrieve the list of offenses')
SampleUtilities.pretty_print_response(response)
sys.exit(1)
# Since the previous call had no parameters and response has a lot of text,
# we'll just print out the number of offenses
response_body = json.loads(response.read().decode('utf-8'))
print('Number of offenses retrieved: ' + str(len(response_body)))
# -------------------------------------------------------------------------
# Using the fields parameter with 'GET'
# If you just print out the result of a call to the siem/offenses GET
# endpoint there will be a lot of fields displayed which you have no
# interest in. Here, the fields parameter will make sure the only the
# fields you want are displayed for each offense.
# Setting a variable for all the fields that are to be displayed
fields = '''id%2Cstatus%2Cdescription%2Coffense_type%2Coffense_source%2Cmagnitude%2Csource_network%2Cdestination_networks%2Cassigned_to'''
# Send in the request
SampleUtilities.pretty_print_request(client, 'siem/offenses?fields='+fields, 'GET')
response = client.call_api('siem/offenses?fields=' +fields, 'GET')
# Once again, check the response code
if (response.code != 200):
print('Failed to retrieve list of offenses')
SampleUtilities.pretty_print_response(response)
sys.exit(1)
# This time we will print out the data itself
#SampleUtilities.pretty_print_response(response)
response_body = json.loads(response.read().decode('utf-8'))
print(response_body)
print(type(response_body))
for i in response_body:
print(i)
print("")
for j in response_body:
print(j['id'])
print(j['status'])
print(j['description'])
You can write your own management commands, and invoke them with
myprojectpath/manage.py mycommand args ...
The documentation is here
Note that this is required, if you wish to utilize Django models. There is a lot of environment setup which this will do for you behind the scenes. If you try to just import and use django models into a vanilla Python script, they won't work right.
I'm building a webpage which takes user input and returns a table based on information in my backend. I'm using the web framework Pyramid. My current approach is the following:
Create a Colander Schema and a Deform form object that is rendered using a Chameleon template.
Once the user hits submit, validate the submission and use the input to generate a list of dictionaries.
Encode this result into JSON and feed it to dynatable.js
Display the dynatable below my submission form
Steps 3 and 4 are where I'm having an issue. I don't know what I need to do to expose my list of dictionaries to dynatable. I've read the Pyramid Quick Tutorial, so I have an idea of how to do simple AJAX with a JSON renderer, but I have no idea how to implement this into my current situation.
To give a better idea, my function for processing Deform input is as follows (part of the function and template is adapted from the Deform sample provided on the official Github repo):
#view_config(route_name='query_log', renderer='templates/form.pt')
def query_log(request):
schema = Device().bind(request=request)
# Create a styled button with some extra Bootstrap 3 CSS classes
process_btn = deform.form.Button(name='process', title="Process")
form = deform.form.Form(schema, buttons=(process_btn,), use_ajax=True)
# User submitted this form
if request.method == "POST":
if 'process' in request.POST:
try:
appstruct = form.validate(request.POST.items())
# Save form data from appstruct
print("Enter ID:", appstruct["ID"])
print("Enter date:", appstruct["date"])
# This variable is what I want to feed to dynatable
results = parse_log(appstruct["ID"], appstruct["date"].strftime('%Y-%m-%d'))
json.dumps(results)
# Create ppoup
request.session.flash('Returning Results.')
# Redirect to the page shows after succesful form submission
return HTTPFound("/")
except deform.exception.ValidationFailure as e:
# Render a form version where errors are visible next to the fields,
# and the submitted values are posted back
rendered_form = e.render()
else:
# Render a form with initial default values
rendered_form = form.render()
return {
# This is just rendered HTML in a string
# and can be embedded in any template language
"rendered_form": rendered_form,
}
How would I go about passing this results variable via JSON to Dynatable and have the table rendered below the form?
Try baby steps first.
After validation is successful in your try block:
try:
appstruct = form.validate(request.POST.items())
# following depends on structure of data you need
results = dict("id" = appstruct["ID"],
"date" = appstruct["date"].strftime('%Y-%m-%d'))
data = json.dumps(results)
return dict(data=data)
And in the target template, accept the data parameter, rendering to taste.
Once you have that in place, then you can work on how to pass data via an XHR request, which will depend on your choice of JavaScript library.
I am creating an application using Flask, SQLAlchemy, and Jinja. Almost every page in my application uses a base.html file (which is essentially a shell with a navbar and sidebar), and then builds upon that. I display information in the base.html file that is the result of a SQLAlchemy query:
user.company.users.filter(User.account_approved == False).all()
and right now I am passing it to a single view by using:
#splash.route('/dashboard')
#login_required
def dashboard():
return render_template('templates/dashboard.html', pendingUsers=g.user.company.users.filter(User.account_approved == False).all())
However, this only allows the base.html view to have this information when I load the /dashboard route, and if I load any other route that uses the same base.html file, running {{ pendingUsers}} outputs not text. How can I go about rendering that query in every route that uses base.html? I tried making the query directly in the jinja template, but I could not figure out how to do that (for example, running {{ g.user.company.users }} simply outputted the SQL query for that SQLAlchemy statement.
What you are doing is not going to work because your query is not evaluated when you call it within render_template. Instead, the sql query string is sent as is to the template.
You can use a custom decorator since only want to do this for some views/pages.
def get_pending_users(f):
#wraps(f)
def decorated_function(*args, **kwargs):
pending_users = user.company.users.filter(User.account_approved == False).all()
if g.pending_users is None:
g.pending_users = pending_users
return f(*args, **kwargs)
return decorated_function
In your view, you can call it as:
#app.route('/',methods = ['GET','POST])
#get_pending_users
def whatever():
return render_template('templates/dashboard.html')
Then, in your template, just call g.pending_users
{{ g.pending_users }}
Wrote a very simple function to pull data from the espn api and display in default/index. However default/index is a blank page.
At this point I'm not even trying to parse through the JSON - I just want to see something on my browser.
default.py:
import urllib2
import json
#espn_uri being pulled from models/db.py
def index():
r = urllib2.Request(espn_uri)
opener = urllib2.build_opener()
f = opener.open(r)
status = json.load(f)
return dict(status)
default/index.html:
{{status}}
Thank you!
Try: return dict(status=status)
return dict(status) works because status it itself a dict, and dict(status) just copies it. But it's probably got no key named status, or at least nothing interesting.
And yes, you need =.
As JLundell advises, first return paired data via the dictionary:
return dict(my_status=status)
Second, as you've worked out, use the following to access the returned, rather than the local variable in index.html. Make sure you use the equals sign here or nothing will display
{{=my_status}}
When it comes to JSON, you can return the data using
return my_status.json()
Several other options are available to return data as a list, or to return HTML.
Finally, I recommend that you make use of jQuery and AJAX ($.ajax), so that the AJAX return value can be easily assigned to a JS object. This will also allow you to handle success or errors in the form of JS functions.