Set global constant cross all the view - python

This sounds nasty. I want to set a global variable in the request, which means all my views can refer to that constant by doing:
getattr(request, 'CONSTANT_NAME', None)
However, this variable's value may be changed at some point, which means I have the following code in one of my view:
setattr(request, 'CONSTANT_NAME', VALUE)
I know the way I am doing this is definitely wrong, but I wish to know if there is a correct and clean way to achieve what I am looking for.
I am thinking about middleware, but not sure how to do it. A hint is sufficient.
Thanks in Advance.
UPDATE:
Someone mentioned about Session. I pretty sure it should works. However, it is not clean enough. By using session, I need to create same constant as many times as the total number of sessions server maintaining. In fact, the constant remain the same cross the server and it has to be mutable! The last requirement is the nasty part.

Eventually, I took the way of Middleware. I wrote a custom middleware and set a variable in the middleware, something like,
CONSTANT_NAME = None
It is global.
And a local thread:
_thread_local = threading.local()
which is also global.
Then I have two methods in the middleware,
def get_constant_value()
return getattr(_thread_local, 'CONSTANT_NAME', None)
def set_constant_value(value):
CONSTANT_NAME = value
which can be called from any views.
Then inside my middleware, I have
def process_request(self, request):
_thread_local.CONSTANT_NAME = CONSTANT_NAME
At this point, I call set and get this server-crossed variable from any view I want.
The solution is not perfect (I believe). If anyone got a better idea, let me know please!
Thanks!

Related

Issue with creating/retrieving cookies in Flask

When the class AnonUser is initialized, the code should check if a cookie exists and create a new one if it doesn't. The relevant code snippet is the following:
class AnonUser(object):
"""Anonymous/non-logged in user handling"""
cookie_name = 'anon_user_v1'
def __init__(self):
self.cookie = request.cookies.get(self.cookie_name)
if self.cookie:
self.anon_id = verify_cookie(self.cookie)
else:
self.anon_id, self.cookie = create_signed_cookie()
res = make_response()
res.set_cookie(self.cookie_name, self.cookie)
For some reason, request.cookies.get(self.cookie_name) always returns None. Even if I log "request.cookies" immediately after res.set_cookie, the cookie is not there.
The strange thing is that this code works on another branch with identical code and, as far as I can tell, identical configuration settings (it's not impossible I'm missing something, but I've been searching for the past couple hours for any difference with no luck). The only thing different seems to be the domain.
Does anyone know why this might happen?
I figured out what the problem was. I was apparently wrong about it working on the other branch; for whatever reason it would work if the anonymous user already had some saved collections (what the cookies are used for), and I'm still not sure why that is, but the following ended up resolving the issue:
#app.after_request
def set_cookie(response):
if not request.cookies.get(g.cookie_session.cookie_name):
response.set_cookie(g.cookie_session.cookie_name, g.cookie_session.cookie)
return response
The main things I needed to do were import "request" from flask and realize that I could reference the cookie and cookie name through just referring to the anonymous user ("cookie_session") class where they were set.

Can you set session variables in MAKO files in Pyramid?

So I found this answer regarding setting session variables in a pyramid view file, and then later accessing it in a mako template. ( How to access session variable in Mako template and Pyramid? )
I wanted to know if you could do it the other way around. So instead of:
Pyramid view.py
def thisView(request):
session = request.session
session['selectedclientid'] = 'test' #selectedclient.id
session.save()
webpage.mako
${request.session['selectedclientid']}
Can I swap it so I can do this instead?
webpage.mako
${request.session['selectedclientid'] = '5'}
Pyramid view.py
def thisView(request):
someLogicOn(session['selectedclientid'])
So far I have been unsuccessful in making it work and I'm not sure if it's just due to a lack of understanding how to do it or if it's something that just can't be done. Any advice would be great!
In the typical rendering workflow, the view executes before the renderer. It's not clear how you are intending to correct for that. It's possible to do if you call render yourself within the view, I guess, so I'll show that.
webpage.mako:
<%
request.session['selectedClientId'] = '5'
%>
code:
def thisView(request):
response = render_to_response('webpage.mako', {}, request=request)
someLogicOn(request.session['selectedClientId'])
return response
This is logically a little backward though, so you might want to think twice about what you're doing.

Multiple decorators for a view in Django: Execution order

I am trying to decorate a Django view by two decorators, one for checking login, and one for checking is_active.
The first one is the built-in #login_required, and the second one is the following:
def active_required(function):
dec = user_passes_test(lambda u: u.is_active, '/notallowed', '')
return dec(function)
Now, the decorators in Python work inside out, however the following does not work:
#active_required
#login_required
def foo(request):
...
I want to first check if the user is logged in, and redirect to login page if not, and if he or she is logged in, I want to check whether he or she is active, and if not, perform redirect to '/notallowed'.
What happens is that if the login_required fails, the user is not redirected to the login page, but #active_required is executed, and since the user is null in that case, #active_required decorator fails and the user is redirected to /notallowed.
Changing the order seems to work,
#login_required
#active_required
def foo(request):
...
but I suspect there is something wrong with this approach too.
What is the proper way to combine two decorators, and why does the execution order differ from simple Python decorators?
Now, the decorators in Python work from the inside out
Well I guess that depends on your definition of inside out. In your case, you want #login_required to execute first, and so it should be the "outermost" (top) decorator.
As you noted, your last example works, and is indeed the correct way to do this.
edit
The confusion might be how these particular decorators work.
#login_required(#original_view) returns a new view, which first checks if you are logged in, and then calls original_view
so
#login_required(
#active_required(
#my_view
)
)
first checks if you are logged in, then
first(second) checks if you are active, then
runs my_view
Decorators are applied in the order they appear in the source. Thus, your second example:
#login_required
#active_required
def foo(request):
...
is equivalent to the following:
def foo(request):
...
foo = login_required(active_required(foo))
Thus, if the code of one decorator depends on something set by (or ensured by) another, you have to put the dependent decorator "inside" the depdended-on decorator.
However, as Chris Pratt notes, you should avoid having decorator dependencies; when necessary, create a single new decorator that calls both in the right order.
It only really makes sense to stack decorators if they have truly unique functionality. Based on your description, there's never going to be a scenario where you will want to use active_required but not login_required. Therefore, it makes more sense to have a login_and_active_required decorator that checks both and branches accordingly. Less to type, less to document, and negates the problem.
To explain it a bit more (I was also confused at first): active_required is applied first in a sense that it takes my_view and wraps it in some code. Then login_required is applied and wraps the result in some more code.
But when this wrapped version of my_view is actually invoked, first the code added by login_required is executed (checking that you're logged in), then the code added by active_required is executed (checking that you're active) and then finally my_view is executed.

Python : Singleton class object to persist list between imports ? (Like django admin register)

I want to have dict / list to which I can add values, just like models can be added to the admin register in django !
My attempt : (package -> __init__.py)
# Singleton object
# __init__.py (Package: pack)
class remember:
a = []
def add(data):
a.append[data]
def get():
return a
obj = remember()
# models1.py
import pack
pack.obj.add("data")
# models2.py
import pack
pack.obj.add("data2")
print pack.obj.get()
# We should get: ["data", "data2"]
# We get : ["data2"]
How to achieve the desired functionality ?
Some say that methods can do this if you don't need sub-classing, how to do this with methods ?
Update:
To be more clear :
Just like django admin register any one can import and register itself with admin, so that register is persisted between imports.
If it's a singleton you're after, have a look at this old blog post. It contains a link to a well documented implementation (here).
Don't. If you think you need a global you don't and you should reevaluate how you are approaching the problem because 99% of the time you're doing it wrong.
If you have a really good reason to do it perhaps thread_locals() will really solve the problem you're trying to solve. This allows you to set up thread level global data. Note: This is only slightly better than a true global and should in general be avoided, and it can cause you a lot of headaches.
If you're looking for a cross request "global" then you most likely want to look into storing values in memcached.

Is there a way to know the variable name that URL Dispatcher pass to view?

i dont know if this is possible, but i will explain what i want try !
I made a Context Processor that will load some user information.
I need know, in this context processor, if there is a variable named "group" in the vars list that will be passed to my view, and if is, i will load up more things.
The processor only receive a REQUEST object, and i think with ONLY this is not possible.
But, with REQUEST_PATH (from request) i could make some magic (w/ urls.py) and find the exact view and variable that was choose by django. Is there a simple way to do this (or maybe ... a way ? :D ) ?
---- solution ----
The solution (using what yasar11732 say) is something like this:
x = resolve(request.META["PATH_INFO"])
if 'group_name' in x.kwargs
do_domething()
Thanks ! :)
see: resolve() It does exactly what are you trying to do. Be aware that this function throws an 404 exception if it doesn't find a match, so be ready to catch it.
Could you just add this in selectively on a per-view basis? Then you could do something like this:
def group_processor(request):
# ...
def some_view(request, user, group=None):
# ...
processors = [group_processor] if group else []
context = RequestContext(request, {}, processors)
return render_to_response("my_template.html", context_instance=context)

Categories