Set an editable variable at Flask app initialization - python

I want to set a specific variable when the app STARTS. I may need to edit this variable later on. How can I do this?
I know global variables are bad to use because all users will be affected by one user modifying a global. Is it bad practice to edit a configuration value (I remember reading that somewhere)? If so, what's the best way to do this?
My use case is setting the MongoDB collection name. The user may need to change the collection they're using based on the type of analysis they want to perform.

Since it's specific to each user, store it in the session. If it's not in the session, use the default.
from flask import request, session
#app.route('/change_collection', methods=['POST'])
def change_collection():
session['collection'] = request.form['name']
return '', 204
def get_collection():
name = session.get('collection', 'default')
return my_data[name]

Related

Can I change Django's sessionid token length?

I would like to change the length of Django's sessioid tokens, so instead of 32 characters it would be something insane, like 64 characters. I know that's a lot, but can it be done? Are there reasons to never do something like this?
I know the key length is defined in django.contrib.sessions.backends in class SessionBase, but I can't seem to find instructions how to override backend functions or replace them.
Ps. I'm new to web development, so I find it difficult to understand some of the documentation. With C++ it was so much easier...
Subclassing in Django is just the same as in C++; you just need to define a new class that inherits from the base one and overrides the relevant method.
In your case the session key is defined in the _get_new_session_key method. You need to inherit from whichever session backend you are already using - eg the db, file or cache backends - and define that method. For example:
from django.contrib.sessions.backends.db import SessionStore as OriginalSessionStore
class SessionStore(OriginalSessionStore):
def _get_new_session_key(self):
"Returns session key that isn't being used."
while True:
session_key = get_random_string(64, VALID_KEY_CHARS)
if not self.exists(session_key):
break
return session_key
Now you can use "path.to.module.with.overridden.class" in your SESSION_ENGINE setting.

Django session data obtainable from models.py without key

I want to access a session variable from a model, in order to customize what gets shown in a template using {{item.seller_email}}. relevant code from models.py:
SESSION_STORE = import_module(settings.SESSION_ENGINE).SessionStore
class Item(Action):
def seller_email(self):
seller = self.get_seller()
session = SESSION_STORE()
debug('session: %s' % vars(session))
viewer = fetch(Client, email = session.get('client', None))
administrator = viewer.is_admin() if viewer else False
debug('viewer: %s, administrator: %s' % (viewer, administrator))
if administrator:
return seller.email
else:
return seller.anonymized[16:]
the answer here seems to say that this is not possible nor desired, but I lack the understanding of Django's session mechanism to be sure: Access session / request information outside of views in Django
this seems to indicate that the current session can be retrieved outside of views, though, just by not passing a key: https://docs.djangoproject.com/en/1.6/topics/http/sessions/#using-sessions-out-of-views, but I've tried it both that way and the above way with the same results: an "empty" session is created.
I'm sure there are other, better ways of doing this, and I will find one myself, but can someone familiar with Django internals explain why this is not possible?
Because the model shouldn't know anything about session, that creates unnecessary entanglement(?) beetween different components and violation of MVC pattern.
What I suggest to do, is to call the function, specifying parameters needed to get a proper result, viewer object in this case.
If using the code in the question, how do you expect your model to work if it's used in a management command (where there is no http request and as a result no session) ?
Or from a celery job ?

control flask-cache'ing from a view

I am wondering if there is a way to allow the user to control the caching properties of a given view using Flask-Cache.
For example, I would like for a view to be cached indefinitely unless the user clicks a reload link, in which case the view would be re-generated. I noticed there is an unless kwarg available to #cached decorator, but I am not sure how one would use this.
It seems that I should be able to add a url_for('this_view', dont_cache=True) somewhere on this_view's Jinja template.
You can clear the cache; given a view function and the full path to the route, use:
from flask import current_app
with current_app.test_request_context(path=path):
# the cache key can use `request` so we need to provide the correct
# context here
cache_key = view.make_cache_key()
cache.delete(cache_key)
Here path is the path to the view; you could use path = url_for('this_view') to generate it, and view is the (decorated) function object you used #cache.cached() on. cache is the Flask-Cache object.
Once the cache is cleared, a new request to that view will re-generate it.
If you never set a custom key_prefix (callable or string) then the default cache key for a given view is based on the request.path value; you could use this too:
cache_key = 'view/{}'.format(url_for('this_view'))
cache.delete(cache_key)
but the current_app.test_request_context / view.make_cache_key() dance above will make your cache key re-generation more robust.

(How) can I set session data from inside a django test?

I'm relying on some session data for my django tests.
I was wondering if i could still do that or if i need to rethink my logic.
Anyway, i'm trying to set the session data like this:
self.client.session['last_page_id'] = unicode(self.t1_p5.id)
response = self.client.post(final_page_path, final_page_answers,
follow=True)
So not only is the self.client.session attribute an "empty" after the assignment, but also my session is actually empty at the time it is being used - and yes the value assigned does indeed exist - no AttributeError is raised.
[EDIT]
django version 1.6
I don't know which version of Django you use but in some old docs it is written:
To modify the session and then save it, it must be stored in a variable first (because a new SessionStore is created every time this property is accessed):
Example:
def test_something(self):
session = self.client.session
session['somekey'] = 'test'
session.save()
docs

Django Unittesting adding a variable to the session

In my unittest I need to add a variable to the session, because that variable is used in the view which is being tested. The django documentation says this is possible in the following way (https://docs.djangoproject.com/en/1.3/topics/testing/#django.test.client.Client.session):
def test_something(self):
session = self.client.session
session['somekey'] = 'test'
session.save()
This code example actually doesn't work, because you will get the error that a dict doesn't have a function save. I also tried various other ways to change the contents inside the session dict, but haven't found a way to change it yet.
I know what it means, what i get back is a dict object so it doesnt have the save function. But the session dict also doesn't update when adding keys.
The documentation statues when using self.client.session it should return a SessionStore object instead of a dictionary.
Seems right now there is a bug in Django, so it doesn't work for unauthenticated users to change the session. This is the corresponding ticket: https://code.djangoproject.com/ticket/11475 .
A work around is to create a dummy view in which the session variables are set and calling that view with the Client.get('url_of_dummy_view').
The ticket referenced by #Sam Stoelinga has been closed as a duplicate. The corresponding ticket can be found here.
To save session data you will have to use an authenticated user. I found a solution here.
class BlogAdminTestCase(TestCase):
def setUp(self):
# Setup Test User
User.objects.create_user(
username='foo',
password='bar'
)
# Must login to modify session variables
self.client.login(username='foo', password='bar')
s = self.client.session
s['my_session_variable'] = 'Yay!'
s.save()

Categories

Resources