Best approach for loading settings that can be modified in Flask - python

Hello all fellow StackOverFlow'ers,
I'm making an app in Flask that runs depending on settings that can be changed by administrator via a POST request in their admin-panel,
Actually, the only two things I came up with for doing this is using os.environ.get (Environment variables) [which i'm using now] or insert it to a PostreSQL Database config table and load it up
Anyway I will be storing settings such as a couple of API_URLs and their API_KEY, and some Conditions of checking like a success value where if condition in text .. else is applied to ... where admin can change them via the panel
I'm looking for the best performant approach for doing such thing.
Best regards.

If you're looking for the changes to only apply on a per-user basis (changes made by the admin only affect the admin), check out Flask's sessions. It works like a dictionary, but stores information in a cookie in the user's browser that can be programmatically accessed by Flask. Be warned that this data is stored in plain-text in the user's browser, so don't store anything sensitive here.
On the other hand, if you're looking for changes made by the admin to affect everybody visiting the website, you may just be able to store the settings in a variable, update them when the admin makes changes, and read them when responding to a request. If you want these settings to persist through a server restart, however, you'll need to write them to disk and then load them on server restart and save them to disk when they're changed. If this is a production-grade app and needs to be able to scale, I personally recommend using an SQLite file to store settings (or a SQL database if it really needs to scale), but this is a personal preference of mine. If this is just a personal app, storing settings in text files would be just fine.
Hope this helps!

Related

How to display user inputted blogs in flask production server

I'm using gunicorn and nginx to serve a flask application, my website has a blogging feature where users can write blogs, once they do, their input is saved as an html file (I use tinyMCE to generate it) and a flask view is added to a views.py file. Now, in deployment, I just used
use_reloader=True
This ensured that every time a new file was added, it was detected, now in production, I don't know how to implement it, gunicorn has --reload option but the docs say that it's only for development. Can someone please provide an insight on how to implement this feature? Thanks!
You don't need a new view for every html file. You could use a generic view that renders the appropriate html according to the url requested.

When should I use the Flask.config vs. use flask.session?

Is there a rule for when to use Flask.config vs. flask.session to store variables?
Anything that is static, app-wide, doesn't change much, and has important information for all users, should use config. (e.g. secret keys, options to modify the app from project to project, emails, generic messages)
Session should only be used to store relevant user data as the data is modified through each page. (e.g. user login data, user preferences, user inputs from previous pages)
If you have to save something from Page 1 to Page 5 in your website for that particular user, then use session. Sessions should mainly be used based on the individual user.
Yes, most definitely.
The config is for global, project-level variables: the location of files, keys for any APIs you might be using, your database access settings, things like that.
The session is for variables related to the current user's session on the site: their previous choices on a multi-page form, preferences, login details, etc.
You definitely don't want to get these mixed up.

Can I use Django to prevent direct access to an image file?

I'd like to prevent my web users from simply right clicking an image and copying/sharing the URL. Certain authenticated users have access to certain images, and I'd like to enforce this as much as possible. Non authenticated users should have no access to image files.
It's generally recommended to avoid storing/fetching images from a DB, due to performance issues, from what I have read.
I've considered having a function that reads the file (server side, in python) and inserts it into the webpage (base64 encoded, possibly, or some other way) in the Django view functions. Combined with an .htaccess file that denies external requests, this would likely work, but it seems like it'd be resource intensive.
Is there any other options for enforcing this rule? I realize users can screenshot, save images, etc, but it's my responsibility to enforce these restrictions as much as possible, what are my best options?
edit: I have no experience using a CDN, but would be willing to use this if it's a viable option that covers these needs.
I'll bite.
Session Middleware - not elegant, but it will work
You'll want the images you don't want served publicly to not be served through your standard apache/django static files config.
your session middleware can then check all incoming requests for the path and if the path is your image directory (such as /privateimg/) and the user is not authenticated you can bounce them back out or replace it inline with another image (such as one that has a watermark).
You can check out the django docs on how session middleware works https://docs.djangoproject.com/en/dev/topics/http/sessions/
People can still pass your links around, but only authenticated users can actually see the contents of said links (called gating your content)
To elaborate:
settings.py
GATED_CONTENT = (
'/some_content_dir/', # This is a directory we want to gate
'.pdf', # maybe we want to gate an entire content type
)
MIDDLEWARE_CLASSES = (
... # Out of the box middleware...blah blah
'yourapp.somemodule.sessionmiddleware.GatedContent',
)
Then you have the following app structure
yourapp
|-somemodule
|-sessionmiddleware.py
Now to the meat (yum!)
sessionmiddleware.py
class GatedContent(object):
"""
Prevents specific content directories and types
from being exposed to non-authenticated users
"""
def process_request(self, request):
path = request.path
user = request.user # out of the box auth, YMMV
is_gated = False
for gated in settings.GATED_CONTENT:
if path.startswith(gated) or path.endswith(gated):
is_gated = True
break
# Validate the user is an authenticated/valid user
if is_gated and not user.is_authenticated():
# Handle redirect
You might be interested in XSendfile.
This is most [elegant and] performance choice IMO: actual files will be served by you webserver, while access control to this files will be done using your Django app.
You may google for "django xsendfile", there are lot of useful posts.

Huge Django project

I have a new job and a huge django project (15 apps, more than 30 loc). It's pretty hard to understand it's architecture from scratch. Are there any techniques to simplify my work in the beginning? sometimes it's even hard to understand where to find a form or a view that I need... thnx in advance.
When I come to this kind of problem I open up a notebook and answer the following:
1. Infrastructure
Server configuration, OS etc
Check out the database type (mysql, postgres, nosql)
External APIS (e.g Facebook Connect)
2. Backend
Write a simple description
Write its input/output from user (try to be thorough; which fields are required and which aren't)
Write its FK and its relation to any other apps (and why)
List down each plugin the app is using. And for what purpose. For example in rails I'd write: 'gem will_paginate - To display guestbook app results on several pages'
3. Frontend
Check out the JS framework
Check the main stylesheet files (for the template)
The main html/haml (etc) files for creating a new template based page.
When you are done doing that. I think you are much more prepared and able go deeper developing/debugging the app. Good luck.
Use this http://packages.python.org/django-extensions/graph_models.html
to generate the Relationship diagrams from the models so that you can visually see how the models are related to each other. This will give you nice idea about the app
1) Try to install the site from scratch. You will find what external apps are needed for the site to run.
2) Reverse engineer. Browse through the site and try to find out what you have to do to change something to that page. Start with the url, look up in urls.py, read the view, check the model. Are there any hints to other processes?
3) Try to write down everything you don't understand, and document the answers for future reference.
I would clone the project so you can mess up endlessly.
Then I would start to reduce the code. "What happens if if just remove this function here?
Also get django debug toolbar:
https://github.com/django-debug-toolbar/django-debug-toolbar
A good terminal debugger is also golden, there are many out there, here is an example:
https://github.com/tomchristie/django-pdb
This allow you to halt the code and even inject and mutate parameters in runtime. Just like GDB in C.
If you use FireFox you can install FireBug on it and when you for example submit ajax form you can see at which url send you request after what you can easily find controller which work with this form data. At chrome this utility embedded by default and call by F12 key.

Django multi-user saas

I'm creating a small saas for learning purposes... I know that the best way to go is to have a separate schema for each user... But my saas is a small app and I really don't need separate schemas plus it would complicate stuff (later alterations to the schema)... So I'm going to use the same schema for all users and just append each user's ID to the entry and then display only the user's entries upon login.
Is there a way I can "prepend" user's ID upon login through middleware? Or do I need to adjust all the queries (filter by user's ID)? I already store the user's ID to his entries... so I need this only for select's.
Thank you!
I don't know of any way to automatically filter querysets based on request.user. This is because the ORM is not coupled with django.contrib.auth.
I tried two SaaS designs:
1 database for all sites, and manual filtering on all querysets. Of course this made django.contrib.admin not possible out of the box. It might be possible to enable django.contrib.admin with a really tight setup of django-authority or maybe even other django per-object permission packages (google cached version because djangopackages.com is down ATM).
1 database per site, that's just easier, keeps the code cleaner, and enables django.contrib.admin out of the box, which can be really cool if you install a django admin theme. Also I enabled django.contrib.admindoc as well as django-dbtemplates.
(Apparently in your case, 1 site = 1 user, but the concept is the same)
I prefer the second implementation because it's obviously a lot less development work, which is compensated by a little system administration.

Categories