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.
Related
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
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 using CSS3 accordion effect, and i want to detect if a hacker will
make a script to make a parallel request; ie:
i've a login form and a registration form in the same page, but only
one is visible because there is a CSS3: to access the page, the user
agent must be HTML5 compatible.
the tip i use is:
class Register(tornado.web.RequestHandler):
def post(self):
tt = self.get_argument("_xsrf") + str(time.time())
rtime = float(tt.replace(self.get_argument("_xsrf"), ""))
print rtime
class LoginHandler(BaseHandler):
def post(self):
tt = self.get_argument("_xsrf") + str(time.time())
ltime = float(tt.replace(self.get_argument("_xsrf"), ""))
print ltime
i've used the xsrf variable because it's unique for every user, to
avoid making the server think that the request is coming from the same
machine.
now what i want: how to make the difference between time values:
abs(ltime - rtime) ; mean, how do i access to rtime outside the class,
i just know how to access the value outside the method, i want to make
this operation to detect if the value is small, then the user is using
a script to make a parallel request to kill the server!
in other words (for general python users)
if i have:
class Product:
def info(self):
self.price = 1000
def show(self):
print self.price
>>> car = Product()
>>> car.info()
>>> car.show()
1000
but what if i've another
class User:
pass
then how do make a method that prints me the self.price, i've tried
inheritance, but got error: AttributeError: User instance has no
attribute 'price', so only methods are passed, not attributs?
It sounds like you need to understand Model objects and patterns that use persistant storage of data. tornado.web.RequestHandler and any object that you subclass from it only exists for the duration of your request. From when the URL is received on the server to when data is sent back to the browser via a self.write() or self.finish().
I would recommend you look at some of the Django or Flask tutorials for some basic ideas of how to build a MVC application in Python (There is no Tornado Tutorials that cover this that I know of).
I am trying to get a session recording of everything I do using WWW::Mechanize. It is really important to have the HTML with the input fields filled and saved to a file.
My code:
$m->save_content($file); # Saves the page without any forms filled
$m->field('user_name', $user); #fills the form
# I need to save the html with the filled form
# $m->save_content($file_2); won't do it
# $m->dump_forms; shows that mechanize knows about the filled forms
$m->click('SUBMIT.x');
$m->save_content($file); # Too late, already in a different page
Any ideas? I have seen it working with LWP::UserAgent but I don't have access to the code.
I have tried everything I can come up with but nothing will update content with the values of $m->forms().
EDIT: basically what I want is to have a function of the type:
$updated_content = merge($m->content, $m->dump_forms);
So when I save it I can see what the input that was given to the forms into a html slideshow.
I don't need to save the current state of the object or restore the session after it is closed.
The solution depends on what you are trying to achieve. The save_content method saves only the content of the last HTTP response and not the entire WWW::Mechanize state.
If you want to store a WWW::Mechanize object so that browsing can proceed at any time from a given point, then you need to investigate serializing a blessed object.
My choice would be to use Data::Dump. If you write
use Data::Dump 'dump';
use WWW::Mechanize;
my $mech = WWW::Mechanize->new;
$mech->get('http://www.mysite.com/path/resource.html');
$mech->form_with_fields(qw/ username password /);
$mech->set_fields( username => 'me', password => 'secret');
open my $dump, '>', 'mechanize_freeze.pl' or die $!;
print { $dump } dump $mech;
close $dump or die $!;
… then you should have a file that you can restore in a separate program using
my $oldmech = do 'mechanize_freeze.pl';
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.