Best way to request-scope data in Django? - python

I'm wondering if there's a clever pattern for request-scoping arbitrary information without resorting to either TLS or putting the information in the session.
Really, this would be for contextual attributes that I'd like to not look up more than once in a request path, but which are tied to a request invocation and there's no good reason to let them thresh around in the session.
Something like a dict that's pinned to the request where I can shove things or lazy load them. I could write a wrapper for request and swap it out in a middleware, but I figured I'd check to see what best-practice might be here?

Just assign the dictionary directly to the request. You can do that in middleware or in your view, as you like.

Context processors. They are called once for every request and receive the actual request object - so you can add ANY data to the context, also based on the curent request!

Related

How can I directly retrieve only part of a JSON document, rather than extracting what I need from the whole thing?

I want to make a JSON request with the Python library requests where I only obtain certain JSON objects.
I know that it is really easy to process the JSON object obtained to only focus in the needed information, but that would throttle the request efficiency (in case it is done repeatedly).
As said, I know this is a possibility:
url = 'www.foo.com'
r = requests.get(url).json()
#Do something with r[3]['data4'], the only one who is going to be used.
But how could I directly only obtain r[3]['data4'] from the request?
Short Answer
To answer your question no, you can't but to understand why you need to know what is happening behind the scenes.
Behind the scenes
When you make a request such as r = requests.get('www.foo.bar') you are making a request to the server and you are viewing the result of that request when you do r.json(). This means that you cannot just get r[3]['data'] as you are parsing what the server sends to you unless the server only sends r[3]['data']. It may be possible to filter out everything else apart from that in the response processing but I am unaware of how to do it.
You can't, if the server does not allow it. If the target server allows you to specify fields you want then you can send that field list in your request and server will return you only those fields in JSON. Otherwise your will have to parse full JSON response and get your desired fields.

Dynamically add URL rules to Flask app

I am writing an app in which users will be able to store information that they can specify a REST interface for. IE, store a list of products at /<username>/rest/products. Since the URLs are obviously not known before hand, I was trying to think of the best way to implement dynamic URL creation in Flask. The first way I thought of would be to write a catch-all rule, and route the URL from there. But then I am basically duplicating URL routing capabilities when Flask already has them built-in. So, I was wondering if it would be a bad idea to use .add_url_rule() (docs here, scroll down a bit) to attach them directly to the app. Is there a specific reason this shouldn't be done?
Every time you execute add_url_rule() the internal routing remaps the URL map. This is neither threadsafe nor fast. I right now don't understand why you need user specific URL rules to be honest. It kinda sounds like you actually want user specific applications mounted?
Maybe this is helpful: http://flask.pocoo.org/docs/patterns/appdispatch/
I have had similar requirement for my application where each endpoint /<SOMEID>/rest/other for given SOMEID should be bounded to a different function. One way to achieve this is keeping a lookup dictionary where values are the function that handle the specific SOMEID. For example take a look at this snippet:
func_look_up_dict = {...}
#app.route('<SOMEID>/rest/other', methods=['GET'])
def multiple_func_router_endpoint(SOMEID):
if SOMEID in func_look_up_dict.keys():
return jsonify({'result' = func_look_up_dict[SOMEID]()}), 200
else:
return jsonify({'result'='unknown', 'reason'='invalid id in url'}), 404
so for this care you don't really need to "dynamically" add url rules, but rather use a url rule with parameter and handle the various cases withing a single function. Another thing to consider is to really think about the use case of such URL endpoint. If <username> is a parameter that needs to be passed in, why not to use a url rule such as /rest/product/<username> or pass it in as an argument in the GET request?
Hope that helps.

Is the Global Request variable in Python/Django available?

I have written a plugin that sends a signal to activate my code. However, it doesn't send the user-request object to my code. I am looking for a way to retrieve the current request without modifying the main application. I cannot find any documentation related to global request (like $_SERVER['REMOTE_ADDR'] in PHP).
I would like to know if there are any variable to do like that in Python/Django.
Django doesn't provide a global request object (it would actually be a thread local, not a global). But there are a few techniques you can use to get the same effect yourself: http://nedbatchelder.com/blog/201008/global_django_requests.html
AFAIK it is not available, except you make it available.
You can copy+paste the snippets provided in the other answers, or you can use this library: https://pypi.python.org/pypi/django-crequest
Middleware to make current request always available.
you can attach it to current request via middleware and retrieve it back
https://github.com/jedie/django-tools/blob/master/django_tools/middlewares/ThreadLocal.py
Based on Ned Batchelder's reply I've compiled a solution. Although I wouldn't recommend it for anything but debugging/troubleshooting. There's a better solution on the linked page.
Put module m1 at a project root:
import inspect
def get_request():
for f in inspect.stack():
f_code = inspect.getmembers(f.frame, inspect.iscode)[0][1]
f_locals = [v for (n, v) in inspect.getmembers(f.frame) if n == 'f_locals'][0]
co_varnames = [v for (n, v) in inspect.getmembers(f_code) if n == 'co_varnames'][0]
if 'request' in co_varnames:
return f_locals['request']
Then in any other file:
import m1
print(m1.get_response().path)
You might want to make sure you don't introduce reference cycles. I haven't understood under which particular conditions I must do what exactly. Not that it matters in my case. But your mileage might vary.
One solution is django-middleware-global-request.
It provides a way to get the request from anywhere once the request has been constructed by Django in the first place. It returns None if no request object is available, for example when running in a manage.py shell.
As I know it, you define your Django view using a number of methods like:
def detail(request, some_param):
# [...]
The parameter request contains information about the HTTP request. request.META['HTTP_X_FORWARDED_FOR'] for example, returns the client's IP address.
If your plugin has something to do with requests, its classes and function probably will be instantiated/called from your view. This means you need to pass it the current request object, as it makes no sense to have a global request object around.
In PHP, this is possible, as every request causes the whole code to be executed from scratch, but in Django requests are dispatched by a server and passed around in the framework using HttpRequest objects. Also refer to this part of the Django documentation for more information.

Distinguishing between GET and POST data in CherryPy?

I've been deciding between Python web frameworks for a project of mine and I've really liked how lightweight, flexible, and concise CherryPy is compared to others. The only problem I'm having is I can't find any documentation on how to distinguish between data sent via GET and via POST.
For example, I don't want users to be able to provide their login credentials through a GET request (http://example.com/login?username=user&password=pass) but, according to CherryPy's tutorial, all data is sent as method parameters, no matter what HTTP method they're sent as. Is there some way to say I only want the POST data or do I have to use MethodDispatcher?
Thanks!
See the docs.
A string containing the HTTP method, such as "GET" or "POST". Set
in the "run" phase.
looks like checking cherrypy.request.method is what you want to do.

Is www.example.com/post/21/edit a RESTful URI? I think I know the answer, but have another question

I'm almost afraid to post this question, there has to be an obvious answer I've overlooked, but here I go:
Context: I am creating a blog for educational purposes (want to learn python and web.py). I've decided that my blog have posts, so I've created a Post class. I've also decided that posts can be created, read, updated, or deleted (so CRUD). So in my Post class, I've created methods that respond to POST, GET, PUT, and DELETE HTTP methods). So far so good.
The current problem I'm having is a conceptual one, I know that sending a PUT HTTP message (with an edited Post) to, e.g., /post/52 should update post with id 52 with the body contents of the HTTP message.
What I do not know is how to conceptually correctly serve the (HTML) edit page.
Will doing it like this: /post/52/edit violate the idea of URI, as 'edit' is not a resource, but an action?
On the other side though, could it be considered a resource since all that URI will respond to is a GET method, that will only return an HTML page?
So my ultimate question is this: How do I serve an HTML page intended for user editing in a RESTful manner?
Another RESTful approach is to use the query string for modifiers: /post/52?edit=1
Also, don't get too hung up on the purity of the REST model. If your app doesn't fit neatly into the model, break the rules.
There is no such thing as a RESTful URI. It is false concept as URIs should be completely opaque to the client.
If it helps you to properly implement the HTTP uniform interface by avoiding verbs in your URIs then that's great, but don't feel constrained by what your URI looks like. It is very limiting to think of resource modeling as type of data modelling. A RESTful system usually needs to do way more than just CRUD operations, so you need to be creative about what resources you make available in your system.
If you create a URL and dereferencing it returns a 200 status code, then that URL refers to a resource. If you create another URL and it also returns a 200, then that is a difference resource.
That means:
http://example.org/customer/10.xml
http://example.org/customer/10.json
http://example.org/customer/10?format=xml
http://example.org/customer/10?format=json
are 4 different resources, and
http://example.org/customers
http://example.org/customers?closed=true
http://example.org/customers?page=2&pagelength=20
are also different resources.
Therefore to answer your question, if you do
GET /post/52/edit
and it returns a 200 status code and a representation, then it must be a resource.
Instead of calling it /post/52/edit, what if you called it /post/52/editor?
Now it is a resource. Dilemma averted.
I don't think /object/id/action is part of the REST specification.
Is your editor going to be a generic thing for all objects ? Then maybe your URL should look like
/editor/object/id
The action is an HTTP Verb ( GET,PUT,DELETE,POST ) and is supposed to be a part of the HTTP request and not part of the URL. For a better summary, check out this Wikipedia article on RESTful_web_services.

Categories