Tomé de guía la estructura de diseño que se explica en el libro de Daniel y Audrey Roy Greenfield. También uso python-decouple, una librería que ayuda a separar los parámetros de configuración del código fuente en un archivo de entorno, y que la conocí en ésta entrada del gran blog de Vitor Freitas.
- Virtualenvwrapper que es un conjunto de extensiones para virtualenv de Ian Bicking.
- Visual Studio Code como IDE multiplataforma.
- python-decouple para separar configuraciones y código.
- Git como control de versiones.
- EditorConfig que me ayuda a definir y mantener estilos de codificación consistentes entre diferentes editores e IDEs.
- Lo primero que hago es crear un archivo de entorno
.env
en la raiz del proyecto con los parámetros que queremos ocultar y adicionamos la línea .env al archivo.gitignore
para no enviar este archivo de entorno al repositorio remoto. Seguimos las instrucciones del blog para hacer uso en el settings.py de nuestro archivo de entorno. - Cambiamos el nombre de la carpeta del sitio (directorio de trabajo externo, también conocido como carpeta de repositorio) de
myapp
amyapp_project
. - Creamos una carpeta
config
dentro de ella y movemos los archivos de la carpetamyapp
a ella. - Dentro de esta carpeta
config
, creamos otra de nombresettings
que contendrá los archivos de configuración por cada entorno de ejecución. - Para ello vamos a dividir
settings.py
enbase.py
,local.py
yproduction.py
. En principio con esto estaría bien. Luego podremos incorporartest.py
más adelante para lo necesario a las pruebas. Por ahora lo de las pruebas vamos a ponerlo enbase.py
que contendrá lo común a todos los niveles y será el que se extienda en los demás módulos. - Editamos
manage.py
para que busque la configuración acorde a cada entorno dentro de nuestro nuevo archivo de configuraciones
Cambiamos esto
#!/usr/bin/env python
# blablabla
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myapp.settings")
# blablabla
Por esto
#!/usr/bin/env python
def get_env_variable(var_name):
from decouple import config
try:
return config(var_name)
except KeyError:
error_msg = f'Establezca la variable {var_name} en el archivo de entorno .env'
raise ImproperlyConfigured(error_msg)
if __name__ == "__main__":
DJANGO_EXECUTION_ENVIRONMENT = get_env_variable('DJANGO_EXECUTION_ENVIRONMENT')
if DJANGO_EXECUTION_ENVIRONMENT == 'LOCAL':
os.environ.setdefault(
"DJANGO_SETTINGS_MODULE", "config.settings.local")
if DJANGO_EXECUTION_ENVIRONMENT == 'PRODUCTION':
os.environ.setdefault(
"DJANGO_SETTINGS_MODULE","config.settings.production")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
- Por último, en nuestro archivo de entorno, .env, especificamos la variable de entorno
DJANGO_EXECUTION_ENVIRONMENT = "LOCAL"
así Django irá a buscar la configuración del archivo"config.settings.local"
como le indicamos.
Para que cada app nueva que creamos se coloque dentro de nuestra carpeta de aplicaciones, osea dentro de myapp
, ejecutaremos django-admin startapp new_app
como siempre, pero desde dentro de la carpeta de aplicaciones.
La ventaja que brinda este diseño es que nos quedan todas las apps ordenadas, dentro de la una carpeta de aplicaciones que, por convención, la llamamos igual que el proyecto. Así, si el projecto es grande y hay muchas aplicaciones, va a ser más fácil, navegar por las mismas dentro de una sola carpeta.
Como siempre, va a haber una app llamada core
que va a ser la que contenga el nucleo de nuestra app.
En cada archivo apps.py
debemos cambiar el nombre de la app por default
class RegistrationConfig(AppConfig):
name = 'app_name'
a
class RegistrationConfig(AppConfig):
name = 'myapp.app_name'
En el archivo urls.py
de cada nueva app devemos agregar, antes de la lista urlpatterns
app_name = "app_name"
Para trabajar con los templates de cada app, vamos a crear una carpeta templates
dentro de la carpeta de aplicaciones myapp
. Para organizar los templates, podemos incluirlos dentro de carpetas con los nombres de las apps.
Luego en el archivo de settings base.py
, cambiamos la lista TEMPLATES que vienen por defecto con el proyecto de Django
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
# blablabla
},
]
Por este otro, que incluye el path de nuestro directorio de apps
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
str(APPS_DIR.path('templates')),
],
# blablabla
},
]
Cada vez que agregamos (o modificamos) un modelo nuevo en Django, éste no actualiza la descripción en la tabla "django_content_type" que es la que maneja los nombres de cada modelo sino que agrega un registro nuevo con el nuevo nombre.
Si se cambia el nombre de un modelo que ya estaba en uso, aparte de hacer las migraciones correspondientes, hay que revisar las tablas "django_content_type", "auth_permision" para ver si no hay que eliminar las entradas que hacen referencia al modelo que ya no existe mediante su id.
También hay que revisar la tabla "django_admin_log" que maneja la información histórica de cada ABM que hacemos en un modelo y actualizar el valor anterior de id por el nuevo para no perder el histórico de cambios.