I have a bottle site that loads content via getJSON() requests.
To handle normal requests made when navigating the site, getJSON() requests are made to a Python script which dumps the results in JSON format.
Push/pop state is used to change the URL when the dynamic content is loaded.
To handle this same dynamic content when directly accessing the URL, eg reloading the page, I create a conditional which loads the bottle template and passes the path to the getJSON() request, which then loads the dynamic content.
#route('/')
#route('/<identifier>')
def my_function(identifier='index'):
# do things with certain paths using if and elif conditionals
#
# handle the getJSON() path
elif value_passed_to_getJSON.startswith("part_one/"):
# get the path after / , in this example it should be 'part_two'
my_variable = value_passed_to_getJSON.split("/")[1]
# perform database query with my_variable
response.content_type = 'application/json'
return dumps(cursor)
# and later for direct URL access, eg reloading the page, this essentially routes the query
# back to the getJSON() path handler above.
elif identifier == "part_one/part_two":
return template('site_template',value_passed_to_getJSON="/" + identifier)
This setup is working when the identifier is something like part_one but not in the format above ie part_one/part_two, in that case a 404 is raised.
As another test, if I simply put:
elif identifier == "part_one/part_two":
return "hello"
I also get a 404 with a Firebug error on GET part_two.
I am wondering if this is because the initial route #route('/<identifier>') only contains a single value and forward slash?
Does it need an extra wildcard to handle the two parts of the path?
Demonstrated Solution (per comment below)
#route('/')
#route('/<identifier:path>')
#view('my_template.tpl')
def index(identifier='index'):
if identifier == 'part_one/part_two':
return "hello"
else:
return "something standard"
Related
I want to send data to html in flask framework, i have a function which receives dictionary as a parameter, then there are several functions applied on dictionary. after that final result i want to render in to html page. Its been 48 hours i am trying from different blogs but didn't get precise solution.
imports ...
from other file import other_functions
from other file import other_functions_2
from other file import other_functions_3
app = Flask(__name__, template_folder='templates/')
#app.route("/dashboard")
def calculate_full_eva_web(input:dict):
calculate_gap = other_functions(input)
calculate_matrix = other_functions_2(input)
average = other_functions_3(input)
data = dict{'calculate_gap':calculate_gap, 'calculate_matrix':calculate_matrix,'average':average}
return render_template('pages/dashboard.html', data = data)
if __name__ == "__main__":
app.run(debug=True)
TRACEBACK
Methods that Flask can route to don't take dictionaries as inputs, and the arguments they do take need to be matches by a pattern in the route. (See https://flask.palletsprojects.com/en/1.1.x/api/#url-route-registrations)
You'd get the same error if you changed
#app.route("/dashboard")
def calculate_full_eva_web(input:dict):
to
#app.route("/dashboard")
def calculate_full_eva_web(input):
Your path forward depends on how you want to pass data when you make the request. You can pass key/value pairs via URL parameters and retrieve them via the request.args object. That might be close enough to what you want. (You'll need to remove the argument declaration from calculate_full_eva_web())
Something like
from flask import request
#app.route('/dashboard')
def calculate_full_eva_web():
input = request.args
...
I'm working on some code that pulls course info from Canvas. As pure python, it works fine. If I try to incorporate it with Flask, I get the following error
requests.exceptions.MissingSchema: Invalid URL 'run/api/v1/courses/1234567': No schema supplied. Perhaps you meant http://run/api/v1/courses/1234567?
This is the code in question:
Canvas file
import sys
from canvasapi import Canvas
def getinfo():
canvasurl = "https://canvas.instructure.com/";
canvastoken = #Redacted for this example
try:
canvastoken = sys.argv[1];
canvasurl = sys.argv[2];
except:
print()
#Create a new canvas object passing in the newly aquired url and token
canvas = Canvas(canvasurl, canvastoken);
#print(canv)
# Create a new course oject -- passing in course number as a parameter
# Course number is currently hard coded
print(canvas.get_course(1234567))
Flask file code (the file that I'm trying to run):
from flask import Flask
import canvas
canvas.getinfo()
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
No schema provided usually means you haven't specified the http:// or https:// in the URL.
In the code you provided, I don't see any reference to a run/api/v1/courses/1234567. One possibility is if you are using the url_for method from requests anywhere in your code, try setting _external=True:
url = url_for('relativeURL', _external=True)
This allows Flask to construct an absolute URL (i.e., a URL with domain included).
If you aren't using url_for, check other places in your code where you might be omitting the http or https from the URL.
If you update your question to include the part that refers to the offending URL, we might be able to provide more specific help.
I need to enable some pages to write an arbitrary URL that does not depend on the structure of the site.
For example I have structure:
/
/blog
/blog/blogpost1
/blog/blogpost2
But, for example, I need change url from /blog/blbogpost2 to /some/blogpost/url1
For this, I decided to give the opportunity to handle any URL of the main page of the site.
class IndexPage(RoutablePageMixin, Page):
...
#route(r'^(?P<path>.*)/$')
def render_page_with_special_path(self, request, path, *args, **kwargs):
pages = Page.objects.not_exact_type(IndexPage).specific()
for page in pages:
if hasattr(page, 'full_path'):
if page.full_path == path:
return page.serve(request)
# some logic
But now, if this path is not found, but I need to return this request to the standard handler. How can I do it?
This isn't possible with RoutablePageMixin; Wagtail treats URL routing and page serving as two distinct steps, and once it's identified the function responsible for serving the page (which, for RoutablePageMixin, is done by checking the URL route given in #route), there's no way to go back to the URL routing step.
However, it can be done by overriding the page's route() method, which is the low-level mechanism used by RoutablePageMixin. Your version would look something like this:
from wagtail.core.url_routing import RouteResult
class IndexPage(Page):
def route(self, request, path_components):
# reconstruct the original URL path from the list of path components
path = '/'
if path_components:
path += '/'.join(path_components) + '/'
pages = Page.objects.not_exact_type(IndexPage).specific()
for page in pages:
if hasattr(page, 'full_path'):
if page.full_path == path:
return RouteResult(page)
# no match found, so revert to the default routing mechanism
return super().route(request, path_components)
I have this code below that I'm working on as part of an AI project. I'm looking to get tags that the user searches and return a url of a post with said tags.
from meya import Component
import requests
import json
API_URL = "https://e621.net/post/index.json?limit=1&tags=rating:s+order:random+{tag}"
class e621_call(Component):
"""Produces a e621 post based on the user's tags."""
def start(self):
tag = self.properties.get('tag') or \
self.db.flow.get('tag')
response = requests.get(API_URL.format(tag=tag))
img = response.json()['file_url']
message = self.create_message(text=img)
return self.respond(message=message, action="next")
Everything is fine up until I assign img to the file_url value, which brings up a
TypeError: list indices must be integers, not str
For the record, I am using meya.ai for this, and the packages are not the issue
Your API returns a dictionary inside a list. Get inside the list first then you can do what you wish with the dictionary.
response = requests.get(API_URL)
foo = json.loads(response.content)
file_url = foo[0].get('file_url')
If you plan on having multiple dictionaries returned inside the list, you can just loop through foo and find the multiple urls.
for d in foo:
print d.get('file_url')
Also, I prefer to not use .json() (As you may have noticed I didn't include it in my answer) because that way you can correctly check for the status_code first before proceeding. Otherwise if you get a 404 or a 500 for example, you will get errors.
if response.status_code == 200:
do stuff here
else:
print "Something is wrong"
I found a temporary workthrough, replacing response.json()['file_url'] with response.json()[0]['file_url'] works fine in the AI, although it still gives me the error.
Related to: django - pisa : adding images to PDF output
I've got a site that uses the Google Chart API to display a bunch of reports to the user, and I'm trying to implement a PDF version. I'm using the link_callback parameter in pisa.pisaDocument which works great for local media (css/images), but I'm wondering if it would work with remote images (using a google charts URL).
From the documentation on the pisa website, they imply this is possible, but they don't show how:
Normaly pisa expects these files to be found on the local drive. They may also be referenced relative to the original document. But the programmer might want to load form different kind of sources like the Internet via HTTP requests or from a database or anything else.
This is in a Django project, but that's pretty irrelevant. Here's what I'm using for rendering:
html = render_to_string('reporting/pdf.html', keys,
context_instance=RequestContext(request))
result = StringIO.StringIO()
pdf = pisa.pisaDocument(
StringIO.StringIO(html.encode('ascii', 'xmlcharrefreplace')),
result, link_callback=link_callback)
return HttpResponse(result.getvalue(), mimetype='application/pdf')
I tried having the link_callback return a urllib request object, but it does not seem to work:
def link_callback(uri, rel):
if uri.find('chxt') != -1:
url = "%s?%s" % (settings.GOOGLE_CHART_URL, uri)
return urllib2.urlopen(url)
return os.path.join(settings.MEDIA_ROOT, uri.replace(settings.MEDIA_URL, ""))
The PDF it generates comes out perfectly except that the google charts images are not there.
Well this was a whole lot easier than I expected. In your link_callback method, if the uri is a remote image, simply return that value.
def link_callback(uri, rel):
if uri.find('chart.apis.google.com') != -1:
return uri
return os.path.join(settings.MEDIA_ROOT, uri.replace(settings.MEDIA_URL, ""))
The browser is a lot less picky about the image URL, so make sure the uri is properly quoted for pisa. I had space characters in mine which is why it was failing at first (replacing w/ '+' fixed it).