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.
Related
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__.
I am writing some test code using pure python unittest. I did it like this:
# retrieve the demo object to get the initial attributes
demo = DemoModel.objects.get(id='1')
init_name = demo.name
# use the requests module to send a request to change attributes of demo
requests.post(...)
# retrieve the demo object again to see if it's changed
demo = DemoModel.objects.get(id='1')
assertNotEqual(init_name, demo.name)
Turns out the demo object wasn't changed! I searched and checked for a long time, but, there is no cache in Django getquery, mysql neither.
You said you did this in "pure unittest" and using the requests module. If you're not careful in doing so, it's quite possible that your request failed -- and you aren't checking the status code of your POST. (One possible reason it could fail would be if you don't provide Django's CSRF value, for example, though it might also fail from a permission check, etc).
Do you know if the post returned successfully?
Seems not Django but Mysql transaction issue. See How do I force Django to ignore any caches and reload data?
Is there any basic example that shows how to get POST parameters from the request in mod python custom handler. I have no trouble in GET requests, where I get my arguments from request.args, BUT if method is POST, request.args is None.
Thanks.
request.args stores query string parameters, as mentioned in the documentation.
If you want to get POST variables, you can always read the body of the request (request.read()) and parse it (urldecode in your case).
But keep in mind that, as mentioned on the official mod_python homepage:
Current State of Mod_Python
Currently mod_python is not under active development. This does not mean that it is "dead" as some people have claimed. It smiply means that the code and the project are mature enough when very little is required to maintain it.
Which means you may be better off using something more modern, like mod_wsgi.
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.
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!