Práctica recomendada para la estructura del directorio de trabajo del proyecto Django

174

Sé que en realidad no hay una única forma correcta. Sin embargo, he descubierto que es difícil crear una estructura de directorio que funcione bien y permanezca limpia para todos los desarrolladores y administradores. Hay una estructura estándar en la mayoría de los proyectos en github. Pero no muestra una forma de organizar otros archivos y todos los proyectos en la PC.

¿Cuál es la forma más conveniente de organizar todos estos directorios en la máquina de desarrollo? ¿Cómo los nombra y cómo se conecta y despliega esto en el servidor?

  • proyectos (todos los proyectos en los que está trabajando)
  • archivos fuente (la propia aplicación)
  • copia de trabajo del repositorio (uso git)
  • entorno virtual (prefiero colocar esto cerca del proyecto)
  • raíz estática (para archivos estáticos compilados)
  • raíz multimedia (para archivos multimedia cargados)
  • LÉAME
  • LICENCIA
  • documentos
  • bocetos
  • ejemplos (un proyecto de ejemplo que utiliza la aplicación proporcionada por este proyecto)
  • base de datos (en caso de que se use sqlite)
  • cualquier otra cosa que normalmente necesite para un trabajo exitoso en el proyecto

Los problemas que quiero resolver:

  • Buenos nombres de directorios para que su propósito sea claro.
  • Mantener todos los archivos del proyecto (incluido virtualenv) en un solo lugar, para que pueda copiar, mover, archivar, eliminar todo el proyecto o estimar el uso del espacio en disco fácilmente.
  • Crear múltiples copias de algunos conjuntos de archivos seleccionados, como la aplicación completa, el repositorio o virtualenv, manteniendo una copia única de otros archivos que no quiero clonar.
  • Implementar el conjunto correcto de archivos en el servidor simplemente al sincronizar un directorio seleccionado.
corredor
fuente

Respuestas:

257

Hay dos tipos de "proyectos" de Django que tengo en mi ~/projects/directorio, ambos tienen una estructura un poco diferente .:

  • Sitios web independientes
  • Aplicaciones conectables

Sitio web independiente

En su mayoría proyectos privados, pero no tiene que ser así. Suele verse así:

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

Configuraciones

Las configuraciones principales son las de producción. Otros archivos (por ejemplo staging.py, development.py) simplemente importan todo production.pyy anulan solo las variables necesarias.

Para cada entorno, hay archivos de configuración separados, por ejemplo. producción, desarrollo. Tengo algunos proyectos que también tengo para probar (para el corredor de prueba), puesta en escena (como verificación antes de la implementación final) y configuración de heroku (para implementar en heroku).

Requisitos

Prefiero especificar los requisitos en setup.py directamente. Solo aquellos necesarios para el entorno de desarrollo / prueba en el que tengo requirements_dev.txt.

Algunos servicios (por ejemplo, heroku) requieren tener requirements.txten el directorio raíz.

setup.py

Útil al implementar proyectos usando setuptools. Se agrega manage.pya PATH, por lo que puedo ejecutar manage.pydirectamente (en cualquier lugar).

Aplicaciones específicas del proyecto

Solía ​​poner estas aplicaciones en el project_name/apps/directorio e importarlas usando importaciones relativas.

Archivos de plantillas / static / locale / tests

Puse estas plantillas y archivos estáticos en plantillas globales / directorio estático, no dentro de cada aplicación. Por lo general, estos archivos son editados por personas que no se preocupan por la estructura del código del proyecto o Python. Si es un desarrollador de pila completa que trabaja solo o en un equipo pequeño, puede crear plantillas / directorio estático por aplicación. Realmente es solo una cuestión de gustos.

Lo mismo se aplica para la configuración regional, aunque a veces es conveniente crear un directorio de configuración regional separado.

Por lo general, es mejor colocar las pruebas dentro de cada aplicación, pero generalmente hay muchas pruebas de integración / funcionales que prueban que más aplicaciones funcionan juntas, por lo que el directorio de pruebas globales tiene sentido.

Directorio tmp

Hay un directorio temporal en la raíz del proyecto, excluido de VCS. Se utiliza para almacenar archivos multimedia / estáticos y bases de datos sqlite durante el desarrollo. Todo en tmp podría eliminarse en cualquier momento sin ningún problema.

Virtualenv

Prefiero virtualenvwrappercolocar todos los venvs en el ~/.venvsdirectorio, pero podría colocarlos dentro tmp/para mantenerlos juntos.

Plantilla de proyecto

He creado una plantilla de proyecto para esta configuración, django-start-template

Despliegue

La implementación de este proyecto es la siguiente:

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

Puede usar en rsynclugar de git, pero aún necesita ejecutar un lote de comandos para actualizar su entorno.

Recientemente, hice una [django-deploy][2]aplicación, que me permite ejecutar un comando de administración único para actualizar el entorno, pero lo he usado solo para un proyecto y todavía estoy experimentando con él.

Bocetos y borradores

Borrador de plantillas que coloco dentro del templates/directorio global . Supongo que uno puede crear una carpeta sketches/en la raíz del proyecto, pero aún no la he usado.

Aplicación enchufable

Estas aplicaciones generalmente están preparadas para publicar como código abierto. He tomado el siguiente ejemplo de django-forme

~/projects/django-app/

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

El nombre de los directorios está claro (espero). Puse los archivos de prueba fuera del directorio de la aplicación, pero realmente no importa. Es importante proporcionar READMEy setup.py, por lo tanto, el paquete se instala fácilmente pip.

Tomáš Ehrlich
fuente
¡Gracias! Me gusta tu estructura. Me dio ideas útiles. Buenos puntos sobre el uso de setup.py para los requisitos y la instalación de manage.py en PATH. ¿Podrías mostrar cómo haces lo último? También buen punto sobre el directorio 'tmp'. Prefiero llamarlo 'local', entonces puedo tener 'env', 'tmp' y cualquier cosa también dentro. Esto resuelve el problema de tener demasiados acuerdos con gitignore. Un nuevo problema es que este nombre está demasiado cerca de 'locale'. Tal vez tenga sentido mover 'locale' a la aplicación principal 'project_name', no estoy seguro. Simplemente no quiero cambiar la estructura debido al mal nombre. ¿Alguna sugerencia?
Raacer 05 de
Cuando use setup.py, agregue el scriptsargumento de palabra clave: github.com/elvard/django-start-template/blob/master/project/… Me gusta tmpporque sugiere "algo temporal" que se puede eliminar en cualquier momento. Toplevel localedir no es necesario, puedes colocarlo en cualquier lugar. Simplemente me gusta que sea consistente con directorios estáticos / plantillas.
Tomáš Ehrlich
Mi requisito de capacidad para hacer varias copias de archivos fuente sin copiar otros archivos no se resuelve directamente. Pero el objetivo aún puede archivarse usando git checkouto excluyendo solo un directorio 'tmp' al clonar el directorio del proyecto. Por lo tanto, parece que su estructura cumple con todos los requisitos, y es lo suficientemente clara como para usarla regularmente sin ninguna duda. Estoy aceptando tu respuesta. Gracias.
Raacer
Gracias. Todavía no entiendo lo que quieres decir con "capacidad de hacer varias copias de archivos fuente sin copiar otros archivos". El comando rsync ajustado funcionaría, pero eso no es probablemente lo que quieres decir ...
Tomáš Ehrlich
Por lo general, creo directorio srcdentro de la raíz del proyecto. Esta es la copia de trabajo de los archivos fuente y la raíz del repositorio git. Puedo hacer varias copias de este directorio - src, src.bak, src_tmpy así sucesivamente. Otros directorios no reporto como env, tmp, media, backupresidir en el mismo nivel. Así que en cp -r src src.bakcualquier momento puedo experimentar con git o comparar versiones con una herramienta externa. Si bien tiene archivos locales dentro de su repositorio, tengo repositorio dentro de mi directorio de archivos locales (viceversa). El mejor nombre de mi srcdirectorio es repo.
Raacer
19

Mi respuesta está inspirada en mi propia experiencia laboral, y principalmente en el libro Two Scoops of Django, que recomiendo encarecidamente, y donde puedes encontrar una explicación más detallada de todo. Solo responderé algunos de los puntos, y cualquier mejora o corrección será bienvenida. Pero también puede haber modales más correctos para lograr el mismo propósito.

Proyectos
Tengo una carpeta principal en mi directorio personal donde mantengo todos los proyectos en los que estoy trabajando.

Archivos de origen
Yo personalmente uso la raíz del proyecto django como raíz del repositorio de mis proyectos. Pero en el libro se recomienda separar ambas cosas. Creo que este es un mejor enfoque, así que espero comenzar a hacer el cambio progresivamente en mis proyectos.

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 o Mercurial parecen ser los sistemas de control de versiones más populares entre los desarrolladores de Django. Y los servicios de alojamiento más populares para copias de seguridad de GitHub y Bitbucket .

Entorno virtual
Utilizo virtualenv y virtualenvwrapper. Después de instalar el segundo, debe configurar su directorio de trabajo. El mío está en mi directorio / home / envs , como se recomienda en la guía de instalación de virtualenvwrapper. Pero no creo que lo más importante sea dónde se coloca. Lo más importante cuando se trabaja con entornos virtuales es mantener actualizado el archivo require.txt.

pip freeze -l > requirements.txt 


Carpeta de proyecto de raíz estática


Carpeta de proyecto raíz de medios

README
raíz del repositorio

LICENCIA
raíz del repositorio


Repositorio de documentos raíz. Estos paquetes de Python pueden ayudarlo a facilitar el mantenimiento de su documentación:

Bocetos

Ejemplos

Base de datos

cor
fuente
Gracias por compartir su experiencia. Hay muchos directorios 'project *' en su estructura. Probablemente no uses esos nombres en la vida real, ¿verdad? Digamos que tenemos un proyecto 'todo'. ¿Cómo se nombran estos directorios en tal caso? El problema que veo en su estructura actual es mezclar el repositorio con archivos que no son del repositorio (como señaló anteriormente). Puede ser molesto agregar basura a .gitignore, ¿no? Otra cosa dudosa es mantener el entorno env tan lejos del proyecto en sí. ¿Tiene sentido? ¿Por qué no crear ~ / docs, ~ / statics, etc.? Incluso a git le gusta sentarse cerca de los archivos de origen.
Raacer 01 de
Los nombraría: "todo_proyecto" -> todo -> todo (o tal vez todoapp). Creo que es importante estar en la carpeta del repositorio en la raíz de la jerarquía de directorios. Pero, es solo mi opinión. Sobre el directorio del entorno, cuando necesita configurar el entorno de producción, ya ha terminado de escribir: pip install -U -r require.txt. Pero, como dije, no hay una solución para todo.
cor
Entonces, la ruta a la aplicación principal es "projects / todo_project / todo / todo". La palabra "proyectos" se repite dos veces y la palabra "todo" se repite tres veces. Esto parece "proyectos / proyecto / mi_proyecto / dir_proyecto / proyecto / proyecto". Los nombres son muy poco claros. Este es uno de los principales problemas que estoy tratando de resolver en la estructura de mi directorio. Quiero nombrar los directorios para facilitar la comprensión de la jerarquía. ¿Qué pasa con la raíz del repositorio, podría explicar por qué es importante? También, ¿podría explicar qué tiene de bueno mantener las envías fuera del directorio principal del proyecto?
Raacer
13

No me gusta crear un nuevo settings/directorio. Simplemente agrego archivos con nombre settings_dev.pyy settings_production.pyasí no tengo que editar el BASE_DIR. El siguiente enfoque aumenta la estructura predeterminada en lugar de cambiarla.

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

Pienso esto:

    settings.py
    settings_dev.py
    settings_production.py

es mejor que esto:

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

Este concepto se aplica también a otros archivos.


Normalmente coloco node_modules/y bower_components/en el directorio del proyecto dentro de la static/carpeta predeterminada .

En algún momento un vendor/directorio para submódulos de Git pero generalmente los coloco en la static/carpeta.

isar
fuente
4

Esto es lo que sigo en mi sistema.

  1. Todos los proyectos : hay un directorio de proyectos en mi carpeta de inicio, es decir ~/projects. Todos los proyectos descansan en su interior.

  2. Proyecto individual : sigo una plantilla de estructura estandarizada utilizada por muchos desarrolladores llamada django-skel para proyectos individuales. Básicamente se encarga de todos sus archivos estáticos y archivos multimedia y todo.

  3. Entorno virtual : tengo una carpeta virtualenvs dentro de mi casa para almacenar todos los entornos virtuales en el sistema, es decir ~/virtualenvs. Esto me da la flexibilidad de saber cuáles son todos los entornos virtuales que tengo y qué aspecto puedo usar fácilmente

Los 3 anteriores son las principales particiones de mi entorno de trabajo.

Todas las otras partes que mencionó dependen en su mayoría de proyecto a proyecto (es decir, puede usar diferentes bases de datos para diferentes proyectos). Entonces deberían residir en sus proyectos individuales.

Sahil Kalra
fuente
Gracias. Puede ser molesto agregar basura a .gitignore al mezclar el repositorio con archivos que no son del repositorio. ¿No lo es? Algunos de mis proyectos tienen hasta diez y más archivos y directorios de este tipo, por lo que esto es un verdadero problema para mí. Otra cosa dudosa es mantener el entorno env tan lejos del proyecto en sí. ¿Cuál es la flexibilidad en tal solución? ¿Por qué no crear ~ / docs, ~ / statics, etc.? Incluso a git le gusta sentarse cerca de los archivos de origen. Pensé que la flexibilidad es cuando puedo copiar / mover / Archivo / eliminar directorio del proyecto completo, incluyendo virtualenv y puede mantener múltiples envs dentro de un proyecto fácil
raacer
4

Según el Django Project Skeleton, la estructura de directorio adecuada que se puede seguir es:

[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

Consulte https://django-project-skeleton.readthedocs.io/en/latest/structure.html para obtener la última estructura de directorios.

Sachin Vardhan
fuente
77
Odio el enfoque [projectname] / [projectname]!)
raacer
1
django-project-skeleton no es "la documentación de Django". Sería más exacto decir "Según django-project-skeleton, ...".
David Winiecki
0

Puede usar el repositorio https://github.com/Mischback/django-project-skeleton .

Ejecute debajo del comando:

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

La estructura es algo como esto:

[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
Ehsan Barkhordar
fuente