ChatGPT解决这个技术问题 Extra ChatGPT

Best practice for Django project working directory structure [closed]

Closed. This question is opinion-based. It is not currently accepting answers. Want to improve this question? Update the question so it can be answered with facts and citations by editing this post. Closed 9 months ago. The community reviewed whether to reopen this question 9 months ago and left it closed: Original close reason(s) were not resolved Improve this question

I know there is actually no single right way. However I've found that it's hard to create a directory structure that works well and remain clean for every developer and administrator. There is some standard structure in most projects on github. But it does not show a way to organize another files and all projects on pc.

What is the most convenient way to organize all these directories on development machine? How do you name them, and how do you connect and deploy this to server?

projects (all projects that your are working on)

source files (the application itself)

working copy of repository (I use git)

virtual environment (I prefer to place this near the project)

static root (for compiled static files)

media root (for uploaded media files)

README

LICENSE

documents

sketches

examples (an example project that uses the application provided by this project)

database (in case sqlite is used)

anything else that you usually need for successful work on project

The problems that I want to solve:

Good names of directories so that their purpose is clear.

Keeping all project files (including virtualenv) in one place, so I can easily copy, move, archive, remove whole project or estimate disk space usage.

Creating multiple copies of some selected file sets such as entire application, repository or virtualenv, while keeping single copy of another files that I don't want to clone.

Deploying right set of files to the server simply by rsyncing selected one dir.


Z
Zulan

There're two kind of Django "projects" that I have in my ~/projects/ directory, both have a bit different structure.:

Stand-alone websites

Pluggable applications

Stand-alone website

Mostly private projects, but doesn't have to be. It usually looks like this:

~/projects/project_name/

docs/               # documentation
scripts/
  manage.py         # installed to PATH via setup.py
project_name/       # project dir (the one which django-admin.py creates)
  apps/             # project-specific applications
    accounts/       # most frequent app, with custom user model
    __init__.py
    ...
  settings/         # settings for different environments, see below
    __init__.py
    production.py
    development.py
    ...
        
  __init__.py       # contains project version
  urls.py
  wsgi.py
static/             # site-specific static files
templates/          # site-specific templates
tests/              # site-specific tests (mostly in-browser ones)
tmp/                # excluded from git
setup.py
requirements.txt
requirements_dev.txt
pytest.ini
...

Settings

The main settings are production ones. Other files (eg. staging.py, development.py) simply import everything from production.py and override only necessary variables.

For each environment, there are separate settings files, eg. production, development. I some projects I have also testing (for test runner), staging (as a check before final deploy) and heroku (for deploying to heroku) settings.

Requirements

I rather specify requirements in setup.py directly. Only those required for development/test environment I have in requirements_dev.txt.

Some services (eg. heroku) requires to have requirements.txt in root directory.

setup.py

Useful when deploying project using setuptools. It adds manage.py to PATH, so I can run manage.py directly (anywhere).

Project-specific apps

I used to put these apps into project_name/apps/ directory and import them using relative imports.

Templates/static/locale/tests files

I put these templates and static files into global templates/static directory, not inside each app. These files are usually edited by people, who doesn't care about project code structure or python at all. If you are full-stack developer working alone or in a small team, you can create per-app templates/static directory. It's really just a matter of taste.

The same applies for locale, although sometimes it's convenient to create separate locale directory.

Tests are usually better to place inside each app, but usually there is many integration/functional tests which tests more apps working together, so global tests directory does make sense.

Tmp directory

There is temporary directory in project root, excluded from VCS. It's used to store media/static files and sqlite database during development. Everything in tmp could be deleted anytime without any problems.

Virtualenv

I prefer virtualenvwrapper and place all venvs into ~/.venvs directory, but you could place it inside tmp/ to keep it together.

Project template

I've created project template for this setup, django-start-template

Deployment

Deployment of this project is following:

source $VENV/bin/activate
export DJANGO_SETTINGS_MODULE=project_name.settings.production
git pull
pip install -r requirements.txt

# Update database, static files, locales
manage.py syncdb  --noinput
manage.py migrate
manage.py collectstatic --noinput
manage.py makemessages -a
manage.py compilemessages

# restart wsgi
touch project_name/wsgi.py

You can use rsync instead of git, but still you need to run batch of commands to update your environment.

Recently, I made django-deploy app, which allows me to run single management command to update environment, but I've used it for one project only and I'm still experimenting with it.

Sketches and drafts

Draft of templates I place inside global templates/ directory. I guess one can create folder sketches/ in project root, but haven't used it yet.

Pluggable application

These apps are usually prepared to publish as open-source. I've taken example below from django-forme

~/projects/django-app/

docs/
app/
tests/
example_project/
LICENCE
MANIFEST.in
README.md
setup.py
pytest.ini
tox.ini
.travis.yml
...

Name of directories is clear (I hope). I put test files outside app directory, but it really doesn't matter. It is important to provide README and setup.py, so package is easily installed through pip.


Thank you! I like your structure. It gave me usefull ideas. Good points about using setup.py for requirements and installing manage.py into PATH. Could you please show how you do the last thing? Also good point about 'tmp' dir. I'd rather name it 'local', then I may have 'env', 'tmp' and anything also inside. This solves the problem of having too many deals with gitignore. A new problem is that this name is too close to 'locale'. Maybe it makes sense to move 'locale' to core app 'project_name', not sure. Just dont want to change structure because of bad name. Any suggestions?
When using setup.py, add scripts keyword argument: github.com/elvard/django-start-template/blob/master/project/… I like tmp because it suggests "something temporary" which can be removed anytime. Toplevel locale dir isn't necessary, you can place it anywhere. I just like it to be consistent with static/templates dirs.
My requirement for ability to make several copies of source files without copying another files is not solved directly. But the goal still may be archived by using git checkout or by excluding just one dir 'tmp' when cloning the project directory. So it seems your structure meets all requirements, and it is clear enough to use on regular basis without any doubt. I'm accepting your answer. Thank you.
Thank you. I still don't understand what you mean by "ability to make several copies of source files without copying another files". Tweaked rsync command would do, but that isn't probably what you mean...
I usually create dir src inside of project root. This is the working copy of source files and the git repository root. I can make several copies of this directory - src, src.bak, src_tmp and so on. Other non-repo dirs like env, tmp, media, backup reside on the same level. So I can just cp -r src src.bak anytime I want to do some experiment with git or to compare versions with external tool. While you have local files inside of your repository, I have repository inside of my local files dir (vice versa). The better name of my src dir is repo.
R
Rajat Singhal

My answer is inspired on my own working experience, and mostly in the book Two Scoops of Django which I highly recommend, and where you can find a more detailed explanation of everything. I just will answer some of the points, and any improvement or correction will be welcomed. But there also can be more correct manners to achieve the same purpose.

Projects I have a main folder in my personal directory where I maintain all the projects where I am working on.

Source Files I personally use the django project root as repository root of my projects. But in the book is recommended to separate both things. I think that this is a better approach, so I hope to start making the change progressively on my projects.

project_repository_folder/
    .gitignore
    Makefile
    LICENSE.rst
    docs/
    README.rst
    requirements.txt
    project_folder/
        manage.py
        media/
        app-1/
        app-2/
        ...
        app-n/
        static/
        templates/
        project/
            __init__.py
            settings/
                __init__.py
                base.py
                dev.py
                local.py
                test.py
                production.py
            ulrs.py
            wsgi.py

Repository
Git or Mercurial seem to be the most popular version control systems among Django developers. And the most popular hosting services for backups GitHub and Bitbucket.

Virtual Environment I use virtualenv and virtualenvwrapper. After installing the second one, you need to set up your working directory. Mine is on my /home/envs directory, as it is recommended on virtualenvwrapper installation guide. But I don't think the most important thing is where is it placed. The most important thing when working with virtual environments is keeping requirements.txt file up to date.

pip freeze -l > requirements.txt 

Static Root Project folder

Media Root Project folder

README Repository root

LICENSE Repository root

Documents Repository root. This python packages can help you making easier mantaining your documentation:

reStructuredText

Sphinx

Sketches

Examples

Database


Thank you for sharing your experience. There is a lot of 'project*' directories in your structure. You probably don't use such names in real life, right? Let's say we have a 'todo' project. How do you name these dirs in such case? The problem that I see in your current structure is mixing repository with non-repository files (as you noted above). It may be annoying to add any trash to .gitignore, is not it? Another dubious thing is keeping the env dir so far from the project itself. Does it make sense? Why not to create ~/docs, ~/statics and so on? Even git likes to sit near the source files.
I would name them: "todo_project" -> todo -> todo (or maybe todoapp). I think that is important beeing the repository folder in the root of the direcectory hierarchy. But, is just my opinion. About the environment directory, when you need to setup the production environment, you are done with just typeing: pip install -U -r requirements.txt. But, as I said, there is not one solution for everything.
So the path to main app is "projects/todo_project/todo/todo". Word "projects" repeated twice, and word "todo" repeated three times. This seems like "projects/project/my_project/project_dir/project/project". The names are very unclear. This is one of major problems that I'm trying to solve in my directory structure. I want to name the directories to make it easy to understand the hierarchy. What about repository root, could you please explain why it's important? Also could you please explain what is good about keeping envs outside of main project dir?
i
isar

I don't like to create a new settings/ directory. I simply add files named settings_dev.py and settings_production.py so I don't have to edit the BASE_DIR. The approach below increase the default structure instead of changing it.

mysite/                   # Project
    conf/
        locale/
            en_US/
            fr_FR/
            it_IT/
    mysite/
        __init__.py
        settings.py
        settings_dev.py
        settings_production.py
        urls.py
        wsgi.py
    static/
        admin/
            css/           # Custom back end styles
        css/               # Project front end styles
        fonts/
        images/
        js/
        sass/
    staticfiles/
    templates/             # Project templates
        includes/
            footer.html
            header.html
        index.html
    myapp/                 # Application
        core/
        migrations/
            __init__.py
        templates/         # Application templates
            myapp/
                index.html
        static/
            myapp/
                js/  
                css/
                images/
        __init__.py
        admin.py
        apps.py
        forms.py
        models.py
        models_foo.py
        models_bar.py
        views.py
    templatetags/          # Application with custom context processors and template tags
        __init__.py
        context_processors.py
        templatetags/
            __init__.py
            templatetag_extras.py
    gulpfile.js
    manage.py
    requirements.txt

I think this:

    settings.py
    settings_dev.py
    settings_production.py

is better than this:

    settings/__init__.py
    settings/base.py
    settings/dev.py
    settings/production.py

This concept applies to other files as well.

I usually place node_modules/ and bower_components/ in the project directory within the default static/ folder.

Sometime a vendor/ directory for Git Submodules but usually I place them in the static/ folder.


S
Sachin Vardhan

As per the Django Project Skeleton, the proper directory structure that could be followed is :

[projectname]/                  <- project root
├── [projectname]/              <- Django root
│   ├── __init__.py
│   ├── settings/
│   │   ├── common.py
│   │   ├── development.py
│   │   ├── i18n.py
│   │   ├── __init__.py
│   │   └── production.py
│   ├── urls.py
│   └── wsgi.py
├── apps/
│   └── __init__.py
├── configs/
│   ├── apache2_vhost.sample
│   └── README
├── doc/
│   ├── Makefile
│   └── source/
│       └── *snap*
├── manage.py
├── README.rst
├── run/
│   ├── media/
│   │   └── README
│   ├── README
│   └── static/
│       └── README
├── static/
│   └── README
└── templates/
    ├── base.html
    ├── core
    │   └── login.html
    └── README

Refer https://django-project-skeleton.readthedocs.io/en/latest/structure.html for the latest directory structure.


I hate the [projectname]/[projectname] approach!)
django-project-skeleton is not "the Django Documentation". It would be more accurate to say "As per django-project-skeleton, ...".
S
Sahil kalra

Here is what I follow on My system.

All Projects: There is a projects directory in my home folder i.e. ~/projects. All the projects rest inside it. Individual Project: I follow a standardized structure template used by many developers called django-skel for individual projects. It basically takes care of all your static file and media files and all. Virtual environment: I have a virtualenvs folder inside my home to store all virtual environments in the system i.e. ~/virtualenvs . This gives me flexibility that I know what all virtual environments I have and can look use easily

The above 3 are the main partitions of My working environment.

All the other parts you mentioned are mostly dependent on project to project basis (i.e. you might use different databases for different projects). So they should reside in their individual projects.


Thank you. It may be annoying to add any trash to .gitignore when mixing repository with non-repository files. Is not it? Some of my projects have up to ten and more such files and dirs, so this makes real problem for me. Another dubious thing is keeping the env dir so far from the project itself. What is the flexibility in such solution? Why not to create ~/docs, ~/statics and so on? Even git likes to sit near the source files. I thought flexibility is when I can just copy/move/archive/remove whole project directory including virtualenv and can maintain multiple envs within one project easily
E
Ehsan Barkhordar

You can use https://github.com/Mischback/django-project-skeleton repository.

Run below command:

$ django-admin startproject --template=https://github.com/Mischback/django-project-skeleton/archive/development.zip [projectname]

The structure is something like this:

[projectname]/                  <- project root
├── [projectname]/              <- Django root
│   ├── __init__.py
│   ├── settings/
│   │   ├── common.py
│   │   ├── development.py
│   │   ├── i18n.py
│   │   ├── __init__.py
│   │   └── production.py
│   ├── urls.py
│   └── wsgi.py
├── apps/
│   └── __init__.py
├── configs/
│   ├── apache2_vhost.sample
│   └── README
├── doc/
│   ├── Makefile
│   └── source/
│       └── *snap*
├── manage.py
├── README.rst
├── run/
│   ├── media/
│   │   └── README
│   ├── README
│   └── static/
│       └── README
├── static/
│   └── README
└── templates/
    ├── base.html
    ├── core
    │   └── login.html
    └── README