El artículo responderá a la pregunta que causó la pérdida de tiempo para muchos programadores: ¿qué estructura de directorio debería usarse para un proyecto futuro o existente? ¿Qué estructura será más óptima no solo para la concepción actual del proyecto, sino que no será tan dolorosa en el futuro en términos de expandir el proyecto o dividirlo en partes?
Raíz
Y así comenzamos el proyecto. Que sea el proyecto más fácil de myapp. Creamos un directorio para él en la carpeta principal para el desarrollo (tengo este Devel).
mkdir myapp cd myapp
En el futuro, todas las acciones estarán dentro del catálogo del proyecto principal.
Git
Inicializar un repositorio vacío
git init
.gitignore
# *.pyc *.pyo **/__pycache__/ # **/config/ # **/data/ **/logs/ # ( ) **/bin/
Leeme
El siguiente paso es crear el archivo README requerido. Este archivo contiene la descripción principal y clave de nuestro futuro proyecto. Algunos crean un archivo de texto / sin formato llamado README.txt. En portales grandes, se aceptan repositorios para el estándar Markdown con el nombre README.md. Prefiero html, porque es más conveniente para mí hacer selecciones de color, incrustar enlaces, imágenes y otros elementos multimedia, abrir en un navegador, incrustar piezas de código en las etiquetas <pre> y <code>, usar marcos ya preparados como Bootstrap para la decoración y otra magia fuera de Hogwarts. En consecuencia, el nombre README.html
touch README.html
Si el proyecto es realizado por varios equipos, entonces recomiendo que cada equipo tenga su propio archivo README dentro de cada módulo, componente, biblioteca, etc.
App
Nombro el directorio principal de la aplicación de la misma manera que el directorio del proyecto. En el caso de este artículo, myapp
mkdir myapp touch myapp/__init__.py
Módulos y Componentes
Dentro del directorio de la aplicación, se crea __init__.py de forma predeterminada, que contiene el código de inicialización de la aplicación y conecta todas las partes necesarias a la aplicación. En particular, estos son Blueprints para URL de una sola rama o espacio de nombres para la lógica de un servicio separado, pero con diferentes URL (un ejemplo simple es crear un espacio de nombres para un servicio de artículos de blog, donde hay rutas claramente diferentes del formulario / páginas y / página / ID)
mkdir myapp/bp_component touch myapp/bp_component/__init__.py
o
mkdir myapp/ns_component touch myapp/ns_component/__init__.py
Modelo DB
El modelo de base de datos contiene el código de inicialización de la base de datos, así como las conexiones. Y, por supuesto, la estructura de tablas y relaciones. También es deseable seleccionar tablas en archivos separados en función de la lógica empresarial de la aplicación. La descripción de varias clases de tablas y enlaces en un archivo separado es conveniente porque puede reutilizar fácilmente el código copiando el archivo deseado a otro proyecto o usar enlaces simbólicos al archivo desde la biblioteca compartida para diferentes proyectos.
mkdir myapp/models touch myapp/models/__init__.py touch myapp/models/page.py
Plantillas para el motor de plantillas
Algunas aplicaciones (principalmente aplicaciones web) se caracterizan por el uso de plantillas para generar páginas de hoja. Dado que el objetivo principal es separar el código ejecutable de la presentación de datos, este paso ayudará al equipo a ahorrar mucho tiempo, esfuerzo y dinero al proporcionar la posibilidad de un trabajo paralelo de programadores y diseñadores.
mkdir myapp/templates mkdir myapp/templates/html mkdir myapp/templates/js mkdir myapp/templates/css
Observo que en este caso, el subdirectorio js y css no son para almacenar bibliotecas de JavaScript estáticas o estilos CSS, sino para código mutable, código de parámetro o código de inserción. Por ejemplo, si hay un componente de dibujo de calendario con funcionalidad adicional conectada a los botones, será mucho más conveniente colocar el componente de calendario en js y habilitar el componente en archivos html, pero con los parámetros necesarios. Tal vez esto le parezca una mierda a alguien, pero es mucho mejor que crear una biblioteca de calendario estática lista para usar, y después de medio año o un año para comprender que necesita agregar un par de tres propiedades y métodos más al componente (por ejemplo, hacer datepicker no solo en forma de un mes, sino y agrega la capacidad de convertirlo en un calendario durante un año), y qué tipo de magia había dentro, nadie lo recordaría. Los insertos le darán más transparencia.
Estática
Aquí, todos los estilos principales que nunca cambian (o cambian extremadamente raramente) son estilos, imágenes, sonidos, bibliotecas JS y marcos.
mkdir myapp/static mkdir myapp/static/css mkdir myapp/static/js mkdir myapp/static/images
Biblioteca de funciones
La facilidad para conectar bibliotecas depende principalmente del lenguaje y el marco en el núcleo de la aplicación. NO hay bibliotecas que estén conectadas desde repositorios y sean compatibles con desarrolladores independientes. Aquí están sus propias funciones de ayuda. Por ejemplo, tengo algunas funciones de decorador al procesar una ruta, pero antes de llamar a la función principal.
mkdir myapp/lib touch myapp/lib/__init__.py
Configuraciones y configuración
¿Cómo almacenar la configuración que define la configuración global de la aplicación? Cuántas peleas hubo al respecto y no contaron. Sin detalles, cómo lo hago: lo almaceno como un módulo de Python en un directorio separado. Archivos internos para diferentes modos de inicio.
mkdir config echo "CONFIG = 'config.devel'" > config/__init__.py touch config/devel.py touch config/prod.py
¿Por qué py? Sí, porque el análisis de XML, YAML, INI y otras tonterías, cuando es bastante fácil crear variables del formulario en cuestión, no ha pasado a nadie:
import os DEBUG = True TITLE = 'SpecialistOff.NET' DIR_BASE = '/'.join(os.path.dirname(os.path.abspath(__file__)).split('/')[:-1]) DIR_DATA = DIR_BASE + '/data' DIR_FILES = DIR_DATA + '/files' MIMETYPES = { 'gif': 'image/gif', 'jpg': 'image/jpeg', 'jpeg': 'image/jpeg', 'png': 'image/png', 'txt': 'text/plain' } SERVERS = [ {'name': 'server1', 'IP': '8.8.8.8', 'port': '80'} ]
Datos
Los archivos, registros y otros datos cargados durante la operación se almacenan en un directorio de datos separado
mkdir data mkdir data/files
Prueba
Módulos de prueba y accesorios
mkdir tests mkdir tests/fixture touch tests/__init__.py touch test.py chmod +x test.py
La documentación
Toda la documentación del proyecto debe mantenerse separada. Utilizo el directorio doc para esto y lo almaceno como páginas web estáticas con un punto de entrada index.html. Esto es conveniente porque puedo compartir un directorio de documentación separado a través de cualquier servidor web. O navegue directamente desde el directorio con cualquier navegador web (incluidos los de consola como lynx, elinks).
mkdir doc touch doc/index.html
Despliegue
Todo depende de las tareas. Y en los comentarios (en mi humilde opinión) no es particularmente necesario.
mkdir deploy touch deploy/requirements.txt touch deploy/build.sh mkdir deploy/config touch deploy/config/__init__.py touch deploy/config/demo.py mkdir deploy/cron touch deploy/cron/myapp mkdir deploy/docker touch deploy/docker/Dockerfile touch deploy/docker/docker-compose.yml mkdir deploy/nginx touch deploy/nginx/myapp.conf mkdir deploy/uwsgi touch deploy/uwsgi/conf.ini mkdir deploy/uwsgi/conf.d touch deploy/uwsgi/conf.d/myapp.conf
Registro
Aquí puede agregar registros para los lanzamientos de prueba o las conclusiones de la propia aplicación.
mkdir logs
Scripts de ayuda y utilidades
mkdir utils touch utils/useradd.py chmod +x utils/useradd.py
En lugar de una conclusión
En principio, eso es todo. ¿Por qué soy tan lacónico? Porque el código hablará por mí mejor que yo. El resto de mis comentarios pueden confundir o generar controversia sobre qué enfoque será mejor / peor.