bottle.py URL routing & reverse howto? - python

Sample Bottle.py code:
#route('/show_<name>')
def show(name):
return ''
My question is:
Given a URL, how do we get the view function? E.g. the URL is /show_magic, I need to know the show() function is responsible for this request URL
Given a route (not Router!!) and parameters, how to get the URL? e.g. I need a function called reverse which reverse(default_app().routes[0], name='me') == '/show_me'

you might want to consider named routes
#route('/show_<item_name>', name='item_show')
def show(item_name):
return ''
now given the route name and params how to get the URL? we use get_url
get_url('item_show', item_name='my_item')
http://nongraphical.com/2012/08/using-bottle-py-in-production/

For your first question, use Bottle.match. Given a path (i.e. '/show_magic') and the method (GET or POST or whatever), the following will return a tuple containing a Route object and its parameters:
default_app().match({'PATH_INFO': path, 'REQUEST_METHOD': method})
The function called is the Route object's callback or call attribute.
For your second question, use the router's build method with the route's rule and kwargs:
default_app().router.build(route.rule, name='me')
That doesn't seem to be documented, but it works.

Related

how to pass GET parameters with Flask using add_url_rule

beginner's question:
is it possible to pass GET request parameters to a route function in Flask using add_url_rule?
I am getting the error message that the verify_username_route function I declare later (that takes 1 parameter) is called without any parameters passed.
self.application_.add_url_rule(self.path_ + '/verify', 'verify', self.verify_username_route, methods=['GET'])
To fetch query string parameters, you use request.args.get('argname') in your function. Nothing is passed in -- it's all done through the globals.
To pass any parameters in your URLs, you can use Flask's built-in patterns. These work for both #app.route decorators and add_url_route methods. Here is your code, with a parameter:
self.application_.add_url_rule(self.path_ + '/verify/<int:val>', 'verify', self.verify_username_route, methods=['GET'])
The important part from this is the exact route: /verify/<int:parameter>. This tells Flask that you want the route to be in the format of /verify/something, where something is any integer. Whatever integer is entered here when the request is made gets passed to your self.verify_username_route as a parameter called val.
Read more about this here.

Why does a function in views.py require a request parameter in this case in Django?

In url.py I have set up a new path within the main urlpatterns list:
path('ko/', views.ko),
I learned that I need to write this function in views.py to get the webpage going:
def ko(request):
return HttpResponse("It's a page")
My question is why doesn't the function work when I leave the parameter blank instead of request?:
def ko():
return HttpResponse("It's a page")
Running the page when I delete the request parameter outputs a TypeError:ko() takes 0 positional arguments but 1 was given.
If I don't have a request input on the function call of views.ko then why is the request parameter necessary when writing the initial function, what is the request parameter doing, and where is this request parameter going into? What are its attributes? I would really appreciate a thorough response on its qualities.
A view function, or view for short, is a Python function that takes a Web request and returns a Web response. So every view must accept an request parameter.
The request object contains metadata about the request, for example what HTTP request method used, The IP address of the client etc. You find the list of HttpRequest here
Also from the documentation.
Once one of the URL patterns matches, Django imports and calls the
given view, which is a Python function (or a class-based view). The
view gets passed the following arguments:
An instance of HttpRequest.
If the matched URL pattern contained no named groups, then the matches
from the regular expression are provided as positional arguments.
The keyword arguments are made up of any named parts matched by the
path expression that are provided, overridden by any arguments
specified in the optional kwargs argument to django.urls.path() or
django.urls.re_path().
Each view function takes an HttpRequest object as its first parameter, which is typically named request

In Flask which arg overrides the other in request.values? (GET or POST)

I'm unsure which values (GET or POST) take precedence in Flask's request.values combined dictionary.
Example:
#app.route('test', methods=['GET','POST'])
def test_url():
a = request.values.get(a)
# URL call has 'a' as GET parameter set to 'one'
# URL call also has 'a' as POST parameter set to 'two'
# which will my variable a contain if I call it as shown above?
print(a)
I would like to know that for the documentation of my Flask application.
Flask's Request class is a subclass of werkzeug's Request.
As can be seen in werkzeug source code, values is a CombinedMultiDict of args (GET parameters) and form (POST parameters), in that order.
Looking at the source of CombinedMultiDict, its __getitem__ and get methods try to obtain the keys from the underlying dicts in the same order as specified during construction.
So, for Request.values it will return value from GET if it exists, otherwise the value from POST.
It will return the value from the GET.

Passing variables through URL to a flask app

Well i've this in my flask app :
#app.route("/changeip/<ip>")
def change_ip(ip) :
return ip
Now if i invoke it like :
http://127.0.0.1:5000/changeip?ip=1.2.2.2
It spits out "URL not found"...what is that i'm doing wrong here?
The first route describes a url with a value as part of the url. The second url describes a route with no variables, but with a query parameter in the url.
If you are using the first route, the url should look like http://127.0.0.1/changeip/1.2.2.2.
If you are using the second url, the route should look like /changeip, the function should be def change_ip():, and the value should be read from request.args['ip'].
Usually the route should describe any arguments that should always be present, and form or query params should be used for user-submitted data.
You should use:
app.route('/something/<ip>')
def function(ip):
And when you are using url_for, you should pass value of ip aswell:
url_for('function', ip='your_ip_address')
The accepted answer is correct, but I wanted to add the method that it appears the OP was originally trying in his http request.
Another way to pass in variables is through the question mark that separates variables in the url, and using requests.
import requests
Then in the method,
#app.route("/changeip")
def change_ip():
return requests.args.get('ip', '')
For the url, you pass the variable in using the question mark delimiter, the way you were originally trying.
http://127.0.0.1:5000/changeip?ip=1.2.2.2

Pyramid invoking a sub request

I'm trying to implement a batch request method in pyramid. I see in the docs that it's done with
subrequest = Request.blank('/relative/url')
request.invoke_subrequest(subrequest)
I'm just wondering how do you pass along the headers and cookies? Is it already done for you or is it
request.invoke_subrequest(subrequest, cookies=request.cookies, headers=request.headers)
What about parameters for different methods? The docs only have a POST keyword arg.
I feel like the docs are a little vague, or I can't find the correct docs on how to do this. Thanks
I'm just wondering how do you pass along the headers and cookies?
From http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/narr/subrequest.html#subrequest-chapter :
The pyramid.request.Request.invoke_subrequest() API accepts two
arguments: a positional argument request that must be provided, and
use_tweens keyword argument that is optional; it defaults to False.
This tells us that the constructor only wants a Request object, and optionally a value for use_tweens, so no, this
request.invoke_subrequest(subrequest, cookies=request.cookies, headers=request.headers)
will not work.
Then, from http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/narr/subrequest.html
It's a poor idea to use the original request object as an argument to
invoke_subrequest(). You should construct a new request instead as
demonstrated in the above example, using
pyramid.request.Request.blank(). Once you've constructed a request
object, you'll need to massage it to match the view callable you'd
like to be executed during the subrequest. This can be done by
adjusting the subrequest's URL, its headers, its request method, and
other attributes. The documentation for pyramid.request.Request
exposes the methods you should call and attributes you should set on
the request you create to massage it into something that will actually
match the view you'd like to call via a subrequest.
So basically, you need to configure your request before you pass it to invoke_subrequest().
Luckily there is an entire page that documents the Request class. There we can find a whole lot options to configure it, etc.
What about parameters for different methods? The docs only have a POST keyword arg.
Also on the Request class documentation page, there is this
method
Gets and sets the REQUEST_METHOD key in the environment.
And on http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/narr/viewconfig.html I found
request_method This value can be a string (typically "GET", "POST",
"PUT", "DELETE", or "HEAD") representing an HTTP REQUEST_METHOD
I must agree with you that the documentation is a little vague here and there, but I assume you can use it like this
request.method = 'POST'
# Or
request.method = 'GET'
# Etc.
Summary
You'll want to do it like this
subrequest = Request.blank('/relative/url')
# Configure the subrequest object
# set headers and other options you need.
request.invoke_subrequest(subrequest)
Note
I am aware this is not a 100% complete answer with some code that you can copy paste and it'll just work (especially regarding configuring the request object), but I think this answer contains some information that, at the very least, will get you on the right track and I hope it will be of some help to you.
The following code worked for me. It copies all (headers, cookies, query string, post parameters, etc.):
def subrequest(request, path):
subreq = request.copy()
subreq.path_info = path
response = request.invoke_subrequest(subreq)
return response
Somewhat late, but based on the above two answers here is how I did this. I didn't quite like the above answer to just copy everything. Looking at the documentation of the blank() method there is a kw argument and it says
All necessary keys will be added to the environ, but the values you pass in will take precedence. If you pass in base_url then wsgi.url_scheme, HTTP_HOST, and SCRIPT_NAME will be filled in from that value.
Assuming that the view's request contains the right header information and cookies that you need for your subrequest, you can use the following code:
#view_config( ... )
def something(request):
...
kwargs = { "cookies": request.cookies,
"host" : request.host,
}
req = Request.blank("/relative/url", **kwargs)
resp = request.invoke_subrequest(req)
Other header information (e.g. accept, accept_encoding, etc.) are properties of pyramid.request objects, and can be added to the kwargs dictionary like shown in the code snippet above.
The object returned by invoke_subrequest() is a Response object documented here.

Categories

Resources