What is the variable that indicates the environment in Django? - django

In Rails, there's an environments variable called RAILS_ENV that tells you which environment you're in. Other than creating my own environment variable, is there a default one that tells you which environment you are in in Django?

As mipadi said, there's no "official" variable like Rails has. There's nothing to stop you from creating your own though. You could use the method S. Lott suggested to separate your settings out into separate files and inside each one have a line like:
DJANGO_ENV = 'Production'
Then you could easily access it anywhere:
from django.conf import settings
if settings.DJANGO_ENV == 'Production':
print "I'm in production!"

Django doesn't have quite the same concept of "environment" like Rails' "production", "development", and "test". The closest thing is the DEBUG variable (set your Django project's settings.py file), which should be True for development and False for production. Outside of settings.py, you can obtain it with:
from django.conf import settings
print settings.DEBUG

Often, many things change between "environments".
We have separate settings files for each environment.
Each environment-specific file starts with
from settings import *
To bring in the default settings for the application as a whole.
We have settings_dev, settings_checkout, settings_qa, settings_prod, etc.

Related

Django, separate settings files with a common part

I'm trying to setup Django with two separate settings files, to be selected via the command line parameter --settings, and that (obviously) must have a common file they both use for the common variables.
So I have the file settings_local.py:
DEBUG = True
from . import settings
And I expected that then in settings I would have been able to access DEBUG.
I found no way at all to do that. I've tried to use globals() in both files, I've tried to use global in both, nothing seems to work.
Obviously I cannot import settings_local from settings: the entire point of this setup is to also have a settings_public.py and call either one from the command line. settings itself should be agnostic to it.
I'm also planning to add some kind of control check to ensure settings is not called directly, such as:
try:
DEBUG
except NameError:
raise ValueError( "This file shouldn't be used directly." )
But the exception is always raised, since DEBUG doesn't seem to appear in settings.
I reiterate, even using globals() in both files does not work.
Searched a lot online, couldn't find anything at all that could help me in this very specific situation. I've found many different situations, that either didn't apply, didn't work, or both.
Django settings are just python modules, therefore you cannot write from . import settings and expect settings to have access to global DEBUG variable. Just imagine importing some module which has access to all your global variables - this not only may break module code, but also can lead to bugs in your code relying to these global variables.
The correct answer depends on how complex your requirements are. If you just want to define some variables in dev / prod settings and use them in base settings file the easiest approach would be to switch to .env / .ini / any other external configuration file. E.g. with environ library your code may look like this:
# settings/base.py
import environ
env = environ.Env()
DEBUG = env.bool('DEBUG', default=False)
# now you can use DEBUG value in this file
print(DEBUG)
# settings/local.py
import os
os.environ['DEBUG'] = 'true'
from project.settings.base import *
del os.environ['DEBUG'] # del for simplicity, ideally should be restored to previous value
I'm also planning to add some kind of control check to ensure settings is not called directly
I'm not sure if this is a good idea. What is the reason behind it? If you want to ensure your settings variables are not conflicting with each other it will be better to check their values, without relying on whether the settings module was imported directly or through prod / dev settings. This can be implemented, if you really want to, you'll just need some flag which will indicate if someone imported your base settings outside of dev / prod settings. But this looks like an unnecessary complexity added to the settings module, which should be as simple and dumb as possible

How to declare settings in an app that later can be generally overriden?

I am coding a reusable django-app and I'd like to set some settings, say in a settings.py file inside the app folder, which later can be overriden by other developer on their settings.py file. Is there a particular way, python-zen-way to achieve this rather than the described above?
For instance in my settings.py the pagiation elements would be...
default_pagination_elements = 9
But I'd like the user of the app to be able to override that in their settings.py...
Which is the best way to achieve this?
Many thanks
One way to allow for a user to provide their own value for a setting is to use getattr and provide a default value
from django.conf import settings
my_setting = getattr(settings, 'MY_SETTING', 'default')
This way if the user has not defined the setting you will still get the default value
For your case:
default_pagination_elements = getattr(settings, 'DEFAULT_PAGINATION_ELEMENTS', 9)

Django: Global settings variables

Suppose I have some global settings for my Django project, stored in a text file for easy editing. I want to load the settings, and then store these variables such that they are accessible from any of my view functions. However, I have read that global variables in Django are discouraged. So, how should I do it? I know how to store these variables in a database, but this seems overkill just for storing a few simple variables.
As alecxe has already pointed out, you can use the settings system. This is the customary way to set values that must be used project-wide. If you read the documentation I've linked too you'll see that they cover very early on that page how to set your own settings.
One thing you must not do when you use Django's settings system is refer to settings at the top level of your modules. For instance if you have a view that does this:
from django.conf import settings
FOO = settings.FOO
(Or alecxe's print statement.) This will prevent values from being overriden. The documentation here goes over the details. I recall having had problems in testing due to this because some of my tests were trying to override the default values, and failed.
The settings system I've mentioned above should be used for values that are meant to be set at start up and not changed afterwards. If you want to record settings that can be changed by the site's administrator at run time, you should use a database of some sort.
Just store your variables in settings.py, this is the best and preferrable way to store your project-specific settings. Then, you can always access them by importing django.conf.settings:
from django.conf import settings
print settings.MY_SETTING
Hope that helps.

Ways of maintaining separate settings for different environments?

My django project has two environments - development and test. Today I carelessly overwrote the settings.py in test with the one in development. It took me a while to correct the settings in test, which could have been avoided if I have a good way to maintain the two sets of settings separately.
I was thinking to keep two separate copies of settings.py and rename/move them when needed. This, however, is kinda caveman approach. Are there any smarter ways of dealing with this problem?
At the end of your settings.py file, add this:
try:
from settings_dev import *
except ImportError: pass
Where settings_dev.py will contain the dev settings. And in your production env, do not push settings_dev (just ignore it in .gitingore or your source code versioning system.)
So, when ever settings_dev.py is present, the settings.py will be overwritten by the settings_dev.py file.
One more approach by setting the environment variable:
if os.environ.get('DEVELOPMENT', None):
from settings_dev import *
mentioned here: Django settings.py for development and production
I prefer the first one, it's simple and just works.
Split your settings as documented here:
https://code.djangoproject.com/wiki/SplitSettings#SimplePackageOrganizationforEnvironments

How do I create application scope variable django?

How can I create an application scope variable which is loaded when the django app starts, be in memory and accessible by all.
Basically I want to reuse the variable through out the application without reloading it.
Thanks
You could add it to your settings.py file. Or, add it to the __init__.py file inside the app directory.
Are you referring to something like an environment variable? You could load it via init...
__init__.py
import os
os.environ['APP_VAR_WHATEVER'] = 'hello world!'
Python has three levels of namespace — local (specific to the current function or class method), global (specific to the current module), and built-in. That is, Python does not really have project-wide global variables.
If it's a read-only variable you want, you could use settings.py to define the value and import settings from all other modules that want access to the variable.
If it for both reading and writing, I would likely use the database backend I'm already using with Django, instead of a python variable.
If you could provide a more detailed description of what you're trying to achieve, perhaps we could come up with a better suited solution.