How do I setup and alternate directory structure for django? - python

I'm starting on my first large django project and have realized that the default directory structure isn't going to work well.
I saw this question and answer and decided to implement something similar.
Large Django application layout
What do I need to do to make something like this work? How can I change where django looks for apps/modules?

Python works automatically with deep directory structures. That's porbably you didn't find any instructions on how to do it.Here are some instructions on how to get classes and models to work.
If you want to have a module in folder yourproject/apps/firstapp you can just add it to INSTALLED_APPS by adding line 'apps.firstapp',. You will have to add a __init__.py file to each of the directories so that they are recognized as python packages.
When you import classes you can simply use from yourproject.apps.firstapp.filename import yourclass.
You should also make sure all template directories are listed in TEMPLATE_DIRS.

I have two methods to handle this; one for production and one for development.
In development:
Append the path to your apps in your settings.py. In my case, I have my main project in ~/hg/django/project/ and my apps are in ~/hg/django/apps/. So I use:
if DEVEL:
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'apps'))
I also use the production method on my development box. This method has a knock on effect of letting me roll back to the most recent production version by simply commenting out the line path insertion in the settings.py.
In production:
I install the apps using distutils so that I can control deployment per server, and multiple projects running on each server can all access them. You can read about the distutils setup scripts here. Then, to install, you simply:
./setup.py install

if you add:
import os
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
to your settings .py and the following to your manage.py:
sys.path.insert(0, join(settings.PROJECT_ROOT, "apps"))
sys.path.insert(0, join(settings.PROJECT_ROOT, "lib"))
then you can include them in your installed apps just as you would if they were in your project root:
INSTALLED_APPS = (
#local apps
'myapp',
#local libs
'piston_dev',
)
this allows you a bit more freedom to move apps around without having to redeclare imports and such.

Related

Eclipse configuration setup for Django can't find external libraries

I am in the process of migrating my Django project dev environment to Eclipse.
I have Python and Django working properly in Eclipse. However, when I try to add external libraries, the project doesn't find them.
Here is how I have been adding the modules required:
Right-clicking on project and selecting Properties
Selecting the External Libraries tab
Either adding the source folder (which is in my virtual environment) or the egg (which is also there).
However, in both cases when I do this (for the Messages module) I get this error when doing a syncdb:
Error: No module named messages
I have tried restarting Eclipse, but still no luck.
I'm new to django, so that may be not a best practice, but it works fine for me:
Are you using PyDev? If yes, your external libraries are stored in your_workspace/your_project/.pydevproject file like this:
<path>/usr/local/lib/python2.7/dist-packages/django_annoying-0.7.6-py2.7.egg</path>
It seems to me that this paths are used in development time for code completion and checking types and so on... but they must be in your pythonpath when your run your project and Eclipce doesn't put them to PATH automatically.
To ensure that django apps are in PATH I add something like that to my settings_local.py:
# v PATHS SETTINGS v #
import os
import sys
PROJECT_ROOT = os.path.join(os.path.dirname(__file__), '..')
# v 3d-party django-apps v #
DJANGO_APPS_ROOT = os.path.join(PROJECT_ROOT, '..', '..', 'djaddons')
sys.path.insert(0, os.path.join(DJANGO_APPS_ROOT, 'south'))
sys.path.insert(0, os.path.join(DJANGO_APPS_ROOT, 'annoying'))
if CONF_APP_REGISTRATION_ENABLED:
sys.path.insert(0, os.path.join(DJANGO_APPS_ROOT, 'registration'))
# v python libs v #
PYTHON_LIBS_ROOT = os.path.join(PROJECT_ROOT, '..', '..', 'pylibs')
sys.path.insert(0, os.path.join(PYTHON_LIBS_ROOT, 'oauth2'))
sys.path.insert(0, os.path.join(PYTHON_LIBS_ROOT, 'httplib2'))
# ^ END OF PATHS SETTINGS ^ #
(it's a part of my settings.py which is specific for environment and differs on development computer and on the server)
Or you can add sys.path.insert statements to your .wsgi file on server (if using mod_wsgi) and to your manage.py file for testing with manage.py runserver
The most common thing would be that you're adding the wrong paths... compare what you have in the command line with the paths you really added inside Eclipse by running:
import sys
print('\n'.join(sorted(sys.path)))
and fix the paths inside Eclipse.

Python - packages and settings file

I have a python package that needs to pull in settings from my project directory, here is how my project is currently structured:
~/Project/bin/mypackage
- package files
~/Project/myproject/
- project files
- start.py
- settings.py
I guess it's similar to how Django is structured, you have a settings.py file in your project directory that is somehow referenced by the Django system package in your Python directory.
So, if I am running start.py like so:
python ~/Project/myproject/start.py
..and start.py imports and utilizes the mypackage package, is there any way I can reference the settings.py file local to start.py from within the package? Would I have to load the settings file in start.py and store the values in a global? Does anyone know how this is possible?
The way I see it you have several options:
look for settings and import them either from the current working directory or as determined from environment variables. This is the "django way" using DJANGO_SETTINGS_MODULE and PYTHONPATH. This is nice and magical when it works and inconvenient when it doesn't such as in your case when you are running from a different directory.
rely on module search path which will include the directory of the calling package. Nice and simple but the settings will vary based on the caller. For example all you need in mypackage is:
import settings
pass in settings as a variable
The directory containing the script that was used to invoke the python interpreter is added to the PYTHONPATH. It is available at sys.path[0]. See http://docs.python.org/library/sys.html#sys.path
This means that settings should be available from mypackage.mymodule simply by import settings.
However, I would consider handling the loading of settings in start.py and structuring your app so that a settings object (perhaps just a dict) is passed to it.

Managing multiple settings.py files [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to manage local vs production settings in Django?
I have managed to deploy successfully a Django project on Apache's Web Server with mod_wsgi.
I would like some recommendations on how to manage multiple settings.py files. Right now I have one for development and one totally different for production (regarding DB parameters, static content localization, and stuff like that). My settings.py file is versioned (don't know if this is a good practise) and I deploy it with something like:
$ hg archive myproject.tbz2
$ cd /path/of/apache/web/project/location
$ bzip2 -db /home/myself/myproject/myproject.tbz2 | tar -xvf -
It's working OK. But I find myself manipulating multiple settings.py files.
I guess my question is: what are the best practices when deploying DJANGO PROJECTS regarding multiple settings.py file versions?
I use a settings module that is not a single file:
settings/
__init__.py
_base.py
_servers.py
development.py
production.py
testing.py
The __init__.py file is simple:
from _servers import get_server_type
exec("from %s import *" % get_server_type())
The _base.py file contains all of the common settings across all server types.
The _servers.py file contains a function get_server_type() that uses socket.gethostname() to determine what type of server the current machine is: it returns development, production or testing.
Then the other files look a bit like (production.py):
DEBUG=False
TEMPLATE_DEBUG=False
from _base import *
In each of these files, I put in the settings that only apply to this server type.
The trick that seems to be the most common is to maintain both a settings.py and local_settings.py (one for each environment) file.
Environment agnostic settings go into settings.py and at the bottom of the file, you'll import from local_settings.py
try:
from local_settings import *
except ImportError:
pass
You can override any settings.py settings in the appropriate local_settings.py
django-admin.py / manage.py both accept a --settings=mysite.settings option. In development you could explicitly specify --settings=dev_settings. You can also set the DJANGO_SETTINGS_MODULE environment variable in your apache configuration.
Personally, I simply don't check in settings.py. Instead I check in multiple settings files (dev_settings, prod_settings, etc) and symbolically link them to settings.py as desired. This way if I simply checkout my application it won't be runnable until I think about which settings file is appropriate and actually put that settings file in place.
Another suggestion I've heard but I don't particularly like is having a settings.py that dynamically imports a dev_settings.py if it exists. While this may be more convenient I'd be concerned that it's harder to read settings.py and know what the settings will actually be without also looking for overriding values in a dev_settings.py file that may or may not exist.
My preferred way is to load a separate ini file using ConfigParser, based off a single setting or environment variable. Anyway in the django wiki there are many different options described: http://code.djangoproject.com/wiki/SplitSettings

Sys.path modification or more complex issue?

I have problems with importing correctly a module on appengine. My app generally uses django with app-engine-patch, but this part is task queues using only the webapp framework.
I need to import django settings for the app to work properly.
My script starts with:
import os
import sys
sys.path.append('common/')
# Force Django to reload its settings.
from django.conf import settings
settings._target = None
# Must set this env var before importing any part of Django
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
I always get this error, or something related:
<type 'exceptions.ImportError'>: No module named ragendja.settings_pre
because the settings.py file starts with
from ragendja.settings_pre import *
I think I need to add ragendja to sys.path again but I had several tries that didn't work.
Here is my directory:
project/
app.yaml
setting.py
common/
appenginepatch/
ragendja/
setting_pre.py
myapp/
script.py
Is it only a sys.path problem and how do I need to modify it with the correct syntax?
Thanks
App engine patch manipulates sys.path internally. Background tasks bypass that code, so your path will not be ready for Django calls. You have two choices:
Fix the paths manually. The app engine documentation (see the sub-section called "Handling import path manipulation") suggests factoring the path manipulation code into a module that can be imported by your task script.
Eliminate dependencies on django code, if possible. If you can write your task to be pure python and/or google api calls, you're good to go. In your case, this might mean refactoring your settings code.
Why not:
sys.path.append('common/appenginepatch')
since the ragendja is in this directory?

How to import a Django project settings.py Python file from a sub-directory?

I created a sub-directory of my Django project called bin where I want to put all command-line run Python scripts. Some of these scripts need to import my Django project settings.py file that is in a parent directory of bin.
How can I import the settings.py file from a sub-directory of the project?
The code that I use in my command-line script to set into the "Django context" of the project is:
from django.core.management import setup_environ
import settings
setup_environ(settings)
This works fine if the script is in the root directory of my project.
I tried the following two hacks to import the settings.py file and then setup the project:
import os
os.chdir("..")
import sys
sys.path = [str(sys.path[0]) + "/../"] + sys.path
The cruel hack can import settings.py, but then I get the error:
project_module = __import__(project_name, {}, {}, [''])
ValueError: Empty module name
I think your approach may be over-complicating something that Django 1.x provides for you. As long as your project is in your python path, you can set the environment variable DJANGO_SETTINGS_MODULE at the top of your script like so:
import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings'
In your command line script where you need to read your settings, simply import the settings module from 'django.conf' as you would do in your application code:
from django.conf import settings
And presto, you have your settings and a Django-enabled environment for your script.
I personally prefer to set my DJANGO_SETTINGS_MODULE using '/usr/bin/env' in a bash script called 'proj_env' so I don't have to repeat it
#!/bin/bash
proj_env="DJANGO_SETTINGS_MODULE=myproject.settings"
/usr/bin/env $proj_env ${*}
With this, now I can run any python script with my Django application in context:
proj_env python -m 'myproject.bin.myscript'
If you use virtualenv, this also gives you a good place to source the activate script.
etc. etc.
This is going one level up from your question, but probably the best solution here is to implement your scripts as custom manage.py (django-admin.py) commands. This gives you all of Django's functionality (including settings) for free with no ugly path-hacking, as well as command-line niceties like options parsing. I've never seen a good reason to write Django-related command-line scripts any other way.
Add the parent directory to your path:
import sys
sys.path.append('../')
import settings
Update from comments:
Don't forget the __init__.py file in
the directory that has your
settings.py – S.Lott
Let's say your project directory is /opt/someProject/`
This has files like:
manage.py
Now you have you may have your sub directory anywhere, does not matter.
Eg. subdirectory could be like:
/opt/someproject/dir1/dir2
Now for you to import your project settings inside /opt/someProject/dir1/dir2
You need to set your PYTHONPATH variable
export PYTHONPATH=/opt/someproject/
Now to import modules from bin
from someproject import bin

Categories