The Django docs say that I can call settings.configure instead of having a DJANGO_SETTINGS_MODULE. I would like my website's project to do this. In what file should I put the call to settings.configure so that my settings will get configured at the right time?
Edit in response to Daniel Roseman's comment:
The reason I want to do this is that settings.configure lets you pass in the settings variables as a kwargs dict, e.g. {'INSTALLED_APPS': ..., 'TEMPLATE_DIRS': ..., ...}. This would allow my app's users to specify their settings in a dict, then pass that dict to a function in my app that augments it with certain settings necessary to make my app work, e.g. adding entries to INSTALLED_APPS.
What I envision looks like this. Let's call my app "rexe_app". In wsgi.py, my app's users would do:
import rexe_app
my_settings = {'INSTALLED_APPS': ('a','b'), ...}
updated_settings = rexe_app.augment_settings(my_settings)
# now updated_settings is {'INSTALLED_APPS': ('a','b','c'), 'SESSION_SAVE_EVERY_REQUEST': True, ...}
settings.configure(**updated_settings)
Its not quite equivalent, since settings DJANGO_SETTINGS_MODULE updates defaults, found in django.conf.settings.global_settings, while parameter for configure completely ignores them, so you have to add some additional processing.
Beware, first, that you can't modify INSTALLED_APPS on the fly, as they are examined once on settings processing. For example, to apply modifications to INSTALLED_APPS in Apache-deployed application, you need to restart Apache.
Second, as settings are imported, therefore this point is prone to injections of some sorts, and is highly vulnerable to expose them to users.
If this is a meta app, there are two possibilities:
If you want to provide default settings for `django`-wise setting, add following to `default_settings.py` in your app:
INSTALLED_APPS = ('default_app', )
Just make sure you don't import `default_settings.py` in your app, and make your users add to their settings.py
from rexe_app.default_settings import *
INSTALLED_APPS += ('users_app', )
that effectively will set `INSTALLED_APPS` to `('default_app', 'users_app', )` for your end users.
In case you need `rexe_app`-wise settings, you can default them in your app's `__init__.py`:
from django.conf import settings
REXE_APP_CONFIG_PARAM = getattr(settings, 'REXE_APP_CONFIG_PARAM',
'default_param_value')
so when user needs to change default `REXE_APP_CONFIG_PARAM` he needs to just add
INSTALLED_APPS = ('rexe_app')
REXE_APP_CONFIG_PARAM = 'user_param_value'
to his `settings.py`.
It would be in your wsgi script. please have look at the docs.
You could run mysite.settings.configure() instead of os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
If you are using wsgi then call that in your wsgi script before running the app.
If you want to do this for dev server, pass it as command line option (mentioned on the same page).
django-admin.py runserver --settings=mysite.settings
Related
In one of my apps I have a file called lifecycle with types like so
TYPES = {
'viaf:personal': "986a7cc9-c0c1-4720-b344-853f08c136ab", # E21 Person
'viaf:corporate': "3fc436d0-26e7-472c-94de-0b712b66b3f3", # E40 Legal Body
'viaf:geographic': "dfc95f97-f128-42ae-b54c-ee40333eae8c" # E53 Place
}
I want to move them into my settings.py folder so that can be configurable from there. I am new to Django and am not sure how to go about this. What is the best way to go out doing so?
You can literally move that dictionary into your settings.py file and import it from whatever module you use it in:
from django.conf import settings
...
print(settings.TYPES['viaf:personal'])
After some research I decided that turning these into environment variables with default values was the easiest and safest option.
I'm forced to keep my .env file in a non-standard path outside the root of my project (in a separate directory altogether).
Let's say I have my Django project in /var/projects/my_project, though I have my .env file in /opt/envs/my-project/.env where my SECRET_KEY is stored. In my settings.py file, I'd like to explicitly use the .env file at that path so that I can still do this:
from decouple import config
secret_key = config('SECRET_KEY')
I figured it out.
Instead of importing decouple.config and doing the usual config('FOOBAR'), create a new decouple.Config object using RepositoryEnv('/path/to/env-file').
from decouple import Config, RepositoryEnv
DOTENV_FILE = '/opt/envs/my-project/.env'
env_config = Config(RepositoryEnv(DOTENV_FILE))
# use the Config().get() method as you normally would since
# decouple.config uses that internally.
# i.e. config('SECRET_KEY') = env_config.get('SECRET_KEY')
SECRET_KEY = env_config.get('SECRET_KEY')
Hopefully this helps someone.
If you look at the decouple implementation, config is just a pre-instantiated AutoConfig:
config = AutoConfig()
But AutoConfig takes as optional argument search_path so we can do the following:
from decouple import AutoConfig
config = AutoConfig(search_path='/opt/envs/my-project')
Then you can do as usual:
secret_key = config('SECRET_KEY')
Now, django-decouple==2.1 supports having settings.ini and .env files in any parent directory of the project dir.
(And the old methods don't work anymore. - from decouple import Config, RepositoryEnv does not work, AutoConfig does not have search_path as parameter.)
This is convenient because you would want to keep the settings.ini in the project folder on your local machine and you would want to have clean checkouts on the staging/prod server, thus the settings.ini is better located outside the project folder.
Let's say I have the following settings.py:
LOCALE_PATHS = (
'/conf/locale'
)
DEBUG = True
Can I read value of DEBUG from my python code?
Can I get full path to my language file (django.mo) django uses taken into consideration my LOCALE_PATHS value?
Yes, you can import settings and look for your values:
from django.conf import settings
print settings.DEBUG
Included in a separate comment was the following from LA_:
"Thanks, Joseph. If I print settings.LOCALE_PATHS, it prints exactly the value I defined. How could I get the full path django uses?"
What may be useful for you to do is record the absolute path by using the os.path module.
For example, you could do the following:
PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
LOCALE_ABS_PATH = os.path.join(PROJECT_PATH, LOCALE_PATHS[0])
Then you could reference LOCALE_ABS_PATH as the absolute path to the LOCALE_DIRS listed in settings.py
Let me know if this is helpful at all. I'm not entirely sure of the context with which you plan to implement that, but perhaps I could help more if you continue to have trouble.
I am following the polls app tutorial part 3 and I cannot get the templates to be found
This is the exact error
polls/index.html
Request Method: GET
Request URL: http://localhost:8000/polls/
Django Version: 1.4.3
Exception Type: TemplateDoesNotExist
Exception Value:
polls/index.html
Exception Location: c:\Python27\lib\site-packages\django\template\loader.py in find_template, line 138
Python Executable: c:\Python27\python.exe
Python Version: 2.7.2
So in my settings.py I have put the directory there. "C:/Scripts/mysite/template" and created /polls/index.html
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
"C:/Scripts/template"
"C:/Scripts/mysite/template"
)
It for some reason cannot find it though. Any ideas?
This is the exact instruction from the tutorial.
create a directory, somewhere on your filesystem, whose contents Django can access. (Django runs as whatever user your server runs.)
You're missing a comma at the end of the first line:
"C:/Scripts/template", # <--- HERE
"C:/Scripts/mysite/template"
without that, Python automatically concatenates the two strings (because they're inside parens) so that it just becomes "C:/Scripts/templateC:/Scripts/mysite/template".
Debug
from your applications main folder, run the following command: python manage.py shell this is going to bootstrap your app with the settings file.
type from django.conf import settings and hit enter
type settings.TEMPLATE_DIRS and check the output. Do you see the template directories that you specified?
Absolute paths relative to the settings.py file
I generally use absolute paths relative to the settings.py file. That way collaborators can share a main settings file, and no matter what system/environment you deploy to your paths will be correct.
to do this:
# settings.py
import os
# ... other settings
TEMPLATE_DIRS = (
os.path.join(os.path.normpath(os.path.dirname(__file__)), 'templates'),
)
let me know if the debug step didn't help, and i'll try and supply some more help.
Simple question about extending my application
Lets say I have a "Main Application", and in this application I have the following in the _init_.py file:
config.add_route('image_upload', '/admin/image_upload/',
view='mainapp.views.uploader',
view_renderer='/site/upload.mako')
and in the views.py I have:
def uploader(request):
# some code goes here
return {'xyz':xyz}
Now when I create a new application, and I want to extend it, to use the above view and route:
In the new application _init_.py file I would manually copy over the config.add_route code:
config.add_route( 'image_upload', '/admin/image_upload/',
view='mainapp.views.uploader',
view_renderer='mainapp:templates/site/upload.mako'
)
And is that all I would need to do? From this would my application be able to use the view and template from the main application, or is am I missing something else?
Thanks for reading!
You don't have to copy your code to do this. Use the Configurator.include method to include your "Main Application" configuration in your new application. The documentation explains this pretty well both here and here, but the essentially, if you declare your main apps configuration inside a callable:
def main_app_config(config):
config.add_route('image_upload', '/admin/image_upload/',
view='mainapp.views.uploader',
view_renderer='/site/upload.mako')
Then you can include your main app in your new app's configuration like this:
from my.main.app import main_app_config
# do your new application Configurator setup, etc.
# then "include" it.
config.include(main_app_config)
# continue on with your new app configuration