Python Flask request object doesn't contain data until I access it - python

I'm working with a small Python server written with Flask, and I'm seeing some very weird behavior with HTTP request objects.
When I receive a request, I immediately attempt to log request.__dict__. However, upon retrieving my logs, I noticed that request.__dict__ does not contain the actual body of the request (it should be in request.data).
I then decided to log request.data, and instead of None like I was expecting, since I didn't see it in request.__dict__, I saw the contents of the request body.
Even more interestingly, as soon as I placed the request.data line above the request.__dict__ line, the output from logging request.__dict__ also contained the data property.
It's almost like request.data does not exist until I attempt to access it for the first time. Is this some weird behavior with Flask's request object? Are there any other properties that behave like this? What's the best practice for making sure the request object is fully "loaded"?

Flask's (actually Werkzeug's) Request class doesn't have a data attribute to start with: it has a data method wrapped with the #cached_property decorator. As you can see from the implementation of that decorator, when the property is first accessed, it creates an entry in __dict__ to contain the value returned by the function, which has the effect of avoiding the need to recalculate it each time - basically, a form of memoization.
Although the implementation is very clever (as you'd expect from Armin), there's nothing particularly surprising about the effect - there are plenty of ways that an attribute would not be found in __dict__.

Related

What does it mean when written id=-1 in django request?

I'm reading someone's code, and there is written
get_object_or_404(Order, id=-1)
Could someone explain the purpose of id=-1?
Well get_object_or_404 [Django-doc] takes as input a model or queryset, and aims to filter it with the remaining positional and named parameters. It then aims to fetch that object, and raises a 404 in case the object does not exists.
Here we thus aim to obtain an Order object with id=-1. So the query that is executed "behind the curtains" is:
Order.objects.get(id=-1) # SELECT order.* FROM order WHERE id=-1
In most databases ids are however (strictly) positive (if these are assigned automatically). So unless an Order object is explicitly saved with id=-1, this will always raise a 404 exception.
Sometimes however one stores objects with negative id to make it easy to retrieve and update "special" ones (although personally I think it is not a good practice, since this actually is related to the singleton and global state anti-patterns). You thus can look (for example in the database, or in the code) if there are objects with negative ids. If these objects are not created, then this code will always result in a 404 response.

Flask Response vs Flask make_response

I know that Response is what Flask uses by default for http responses. For specific responses format, I usually use make_response. Are there any specific cases where we have to use flask.Response instead of flask.make_response? in other words, does flask.make_response work in all situations or sometimes flask.Response is the only or the better alternative? Thanks!
make_response() gives you a convenience interface, one that will take arguments in more formats than the flask.Response() object takes.
In addition, make_response() uses the Flask.response_class attribute (so app.response_class) to build the response. The default value for Flask.response_class is flask.Response, but you can set this value to a subclass instead.
So you should really always use make_response(), rather than use flask.Response() directly, especially if you want to support swapping out what Response class you actually use for responses.
You may have to use app.response_class directly if it is a subclass that takes arguments that make_response() can't supply.

TwistedWeb: Custom 404 Not Found pages

I am quite surprised I couldn't find anything on this in my Google searching.
I'm using TwistedWeb to make a simple JSON HTTP API. I'd like to customize the 404 page so it returns something in JSON rather than the default HTML. How might I do this?
There is no API in Twisted Web like something.set404(someResource). A NOT FOUND response is generated as the default when resource traversal reaches a point where the next child does not exist - as indicated by the next IResource.getChildWithDefault call. Depending on how your application is structured, this means you may want to have your own base class implementing IResource which creates your custom NOT FOUND resource for all of its subclasses (or, better, make a wrapper since composition is better than inheritance).
If you read the implementation of twisted.web.resource.Resource.getChild you'll see where the default NOT FOUND behavior comes from and maybe get an idea of how to create your own similar behavior with different content.

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.

Best way to request-scope data in Django?

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!

Categories