Django项目工作目录结构的最佳实践


173

我知道实际上没有唯一正确的方法。但是,我发现很难创建一个可以正常工作并且对于每个开发人员和管理员而言都保持整洁的目录结构。github上的大多数项目都有一些标准结构。但是它没有显示在PC上组织另一个文件和所有项目的方法。

在开发机器上组织所有这些目录的最便捷方法是什么?您如何命名它们,以及如何连接并将其部署到服务器?

  • 项目(您正在处理的所有项目)
  • 源文件(应用程序本身)
  • 存储库的工作副本(我使用git)
  • 虚拟环境(我更喜欢将其放置在项目附近)
  • 静态根(用于编译的静态文件)
  • 媒体根(用于上传的媒体文件)
  • 自述文件
  • 执照
  • 单据
  • 草图
  • 示例(使用该项目提供的应用程序的示例项目)
  • 数据库(如果使用sqlite)
  • 成功完成项目通常需要的其他任何东西

我要解决的问题:

  • 目录的好名称,以便其目的明确。
  • 将所有项目文件(包括virtualenv)放在一个位置,这样我就可以轻松地复制,移动,归档,删除整个项目或估计磁盘空间使用情况。
  • 创建某些选定文件集的多个副本,例如整个应用程序,存储库或virtualenv,同时保留我不想克隆的其他文件的单个副本。
  • 只需通过同步选定的一个目录,即可将正确的文件集部署到服务器。

Answers:


257

我的~/projects/目录中有两种Django“项目”,它们的结构略有不同:

  • 独立网站
  • 可插拔应用

独立网站

通常是私人项目,但不一定必须如此。通常看起来像这样:

~/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
...

设定值

主要设置是生产设置。其他文件(例如staging.pydevelopment.pyproduction.py仅从中导入所有内容并仅覆盖必要的变量。

对于每种环境,都有单独的设置文件,例如。生产,开发。我还测试了一些项目(用于测试运行程序),登台(作为最终部署之前的检查)和heroku(用于部署到heroku)设置。

要求

我宁愿直接在setup.py中指定要求。我只有开发/测试环境所需的内容requirements_dev.txt

某些服务(例如heroku)需要具有requirements.txt根目录。

setup.py

使用部署项目时很有用setuptools。它添加manage.pyPATH,因此我可以manage.py直接(在任何地方)运行。

专案专用的应用程式

我曾经将这些应用程序放到project_name/apps/目录中,并使用相对导入方式将其导入。

模板/静态/语言环境/测试文件

我将这些模板和静态文件放到全局模板/静态目录中,而不是放在每个应用程序中。这些文件通常由根本不关心项目代码结构或python的人员编辑。如果您是一个全职的开发人员,独自工作或以小组形式工作,则可以创建按应用程序模板/静态目录。这实际上只是一个品味问题。

尽管有时创建单独的语言环境目录比较方便,但对于语言环境也是如此。

通常最好将测试放置在每个应用程序中,但是通常会有很多集成/功能测试来测试更多的应用程序,因此全局测试目录确实有意义。

Tmp目录

项目根目录中有一个临时目录,不包含在VCS中。它用于在开发过程中存储媒体/静态文件和sqlite数据库。tmp中的所有内容都可以随时删除,没有任何问题。

虚拟环境

我更喜欢virtualenvwrapper将所有venv放置在~/.venvs目录中,但您可以将其放置在里面tmp/以使其保持在一起。

项目模板

我已经为此设置创建了项目模板django-start-template

部署方式

该项目的部署如下:

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

您可以使用rsync代替git,但是仍然需要运行一批命令来更新环境。

最近,我制作了一个[django-deploy][2]应用程序,它允许我运行单个管理命令来更新环境,但是我仅将其用于一个项目,并且仍在尝试中。

草图和草稿

我将模板草案放置在全局templates/目录中。我猜一个人可以sketches/在项目根目录下创建文件夹,但是还没有使用过。

可插拔应用

这些应用通常准备以开源形式发布。我从django-forme采取以下示例

~/projects/django-app/

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

目录名称很清楚(我希望如此)。我将测试文件放在应用程序目录之外,但这并不重要。重要的是要提供READMEsetup.py,所以包装是很容易通过安装pip


谢谢!我喜欢你的结构。它给了我有用的想法。有关使用setup.py满足要求以及将manage.py安装到PATH的要点。请问您如何做最后一件事?关于“ tmp”目录也很重要。我宁愿将其命名为“ local”,然后可能包含“ env”,“ tmp”以及其他内容。这解决了与gitignore交易过多的问题。一个新问题是该名称与“语言环境”过于接近。不确定是否可以将“语言环境”移至核心应用程序“ project_name”。只是不想因为名字不好而改变结构。有什么建议?
raacer

使用setup.py时,添加scripts关键字参数:github.com/elvard/django-start-template/blob/master/project / ... 我喜欢,tmp因为它建议“临时性”,可以随时删除。顶级locale目录不是必需的,您可以将其放在任何地方。我只是喜欢与static / templates dirs保持一致。
托马什埃利希

我对能够复制源文件的多个副本而不复制另一个文件的能力的要求没有得到直接解决。但是仍然可以通过git checkout克隆项目目录时使用或仅排除一个目录“ tmp” 来归档目标。因此,您的结构似乎满足了所有要求,并且毫无疑问可以定期使用。我接受你的回答。谢谢。
raacer 2014年

谢谢。我仍然不明白您的意思是“能够复制源文件而不复制另一个文件”。调整了rsync命令会做,但不是可能你的意思...
托马什埃利希

我通常src在项目根目录下创建dir 。这是源文件和git信息库根的工作副本。我可以把这个目录的多个副本- ,,src 等等。其他非回购迪尔斯样,,,驻留在同一水平上。因此,我随时可以使用git做一些实验,或使用外部工具比较版本。当您的存储库中有本地文件时,我的本地文件目录中有存储库(反之亦然)。我的目录的更好称呼是。src.baksrc_tmpenvtmpmediabackupcp -r src src.baksrcrepo
raacer

19

我的答案是基于我自己的工作经验而获得的,并且主要是在我强烈推荐的《Two Scoops of Django》一书中,您可以在其中找到所有内容的更详细说明。我只想回答一些问题,欢迎任何改进或纠正。但是也可以有更正确的方式来达到相同的目的。

项目
我的个人目录中有一个主文件夹,其中保存着我正在处理的所有项目。

源文件
我个人将django项目根目录用作项目的存储库根目录。但建议在书中将两者分开。我认为这是一种更好的方法,因此我希望开始在我的项目中逐步进行更改。

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

仓库
Git或Mercurial似乎是Django开发人员中最受欢迎的版本控制系统。以及用于备份GitHubBitbucket的最受欢迎的托管服务。

虚拟环境
我使用virtualenv和virtualenvwrapper。安装第二个目录后,需要设置工作目录。我的目录位于我的/ home / envs目录中,如virtualenvwrapper安装指南中所建议。但是我不认为最重要的是放置在哪里。使用虚拟环境时,最重要的事情是保持Requirements.txt文件为最新。

pip freeze -l > requirements.txt 

静态根
项目文件夹

媒体根
项目文件夹

自述
资料库根目录

许可证
存储库根目录

文档
存储库根目录。这个python软件包可以帮助您更轻松地维护文档:

草图

例子

数据库


感谢您分享经验。您的结构中有很多“ project *”目录。您可能在现实生活中不使用这些名称,对吗?假设我们有一个“待办事项”项目。在这种情况下,您如何命名这些目录?我在您当前结构中看到的问题是将存储库与非存储库文件混合在一起(如上所述)。在.gitignore中添加任何垃圾可能很烦人,不是吗?另一个可疑的事情是使环境目录离项目本身太远。是否有意义?为什么不创建〜/ docs,〜/ statics等?甚至git都喜欢坐在源文件附近。
掠夺者

我将它们命名为:“ todo_project”-> todo-> todo(或者也许todoapp)。我认为将存储库文件夹放在目录层次结构的根目录中很重要。但是,这只是我的意见。关于环境目录,当您需要设置生产环境时,只需键入以下内容即可完成:pip install -U -r requirements.txt。但是,正如我所说,没有一种解决方案可以解决所有问题。
cor

因此,主应用程序的路径为“ projects / todo_project / todo / todo”。单词“项目”重复两次,单词“ todo”重复三次。好像是“ projects / project / my_project / project_dir / project / project”。名称非常不清楚。这是我要在目录结构中解决的主要问题之一。我想命名目录以使其易于理解层次结构。仓库根目录怎么样?您能解释一下它为什么重要的原因吗?还可以请您说明将环境保留在主项目目录之外的好处吗?
raacer 2014年

13

我不喜欢创建新settings/目录。我只添加了名为的文件settings_dev.pysettings_production.py因此无需编辑BASE_DIR。下面的方法增加了默认结构,而不是对其进行更改。

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

我认为这:

    settings.py
    settings_dev.py
    settings_production.py

比这更好:

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

这个概念也适用于其他文件。


我通常把node_modules/bower_components/默认内的项目目录static/文件夹中。

有时vendor/Git子模块的目录,但是通常我将它们放在static/文件夹中。


4

这是我在系统上执行的操作。

  1. 所有项目我的主文件夹中有一个项目目录,~/projects。所有项目都放在其中。

  2. 单个项目:我遵循许多开发人员使用的标准化结构模板django-skel,用于单个项目。它基本上会处理您的所有静态文件和媒体文件以及所有文件。

  3. 虚拟环境:我的家中有一个virtualenvs文件夹,用于存储系统中的所有虚拟环境,即~/virtualenvs。这给了我灵活性,让我知道我拥有的所有虚拟环境以及可以轻松使用的虚拟环境

以上3个是My工作环境的主要分区。

您提到的所有其他部分主要取决于项目之间的关系(即,您可能对不同的项目使用不同的数据库)。因此,他们应该驻留在各自的项目中。


谢谢。将存储库与非存储库文件混合时,将任何垃圾添加到.gitignore可能会很烦人。是不是?我的一些项目最多包含十个以上的此类文件和目录,因此这对我来说确实是个问题。另一个可疑的事情是使环境目录离项目本身太远。这种解决方案的灵活性是什么?为什么不创建〜/ docs,〜/ statics等?甚至git都喜欢坐在源文件附近。我认为灵活性是当我可以复制/移动/存档/删除整个项目目录(包括virtualenv)并可以轻松地在一个项目中维护多个环境时
raacer 2014年

4

根据Django Project Skeleton,可以遵循的正确目录结构是:

[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

有关最新的目录结构,请参阅https://django-project-skeleton.readthedocs.io/en/latest/structure.html


7
我讨厌[projectname] / [projectname]方法!)
raacer19年

1
django-project-skeleton不是“ Django文档”。说“按照django-project-skeleton,...”会更准确。
David Winiecki

0

您可以使用https://github.com/Mischback/django-project-skeleton存储库。

运行以下命令:

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

结构是这样的:

[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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.