template - Django bases de datos múltiples y dinámicas.
django template variable (2)
Abriré con " No debe editar la configuración en tiempo de ejecución ".
Dicho esto, tengo exactamente este mismo problema, donde quiero crear una base de datos única para cada usuario. La razón para hacer esto es que estoy ofreciendo la posibilidad de que el usuario guarde / acceda a / desde una base de datos no almacenada en mi servidor, lo que implica tener múltiples bases de datos, y por lo tanto una para cada usuario.
Esta respuesta NO es la forma recomendada para lograr el objetivo deseado. Me encantaría saber de un django-guru cómo abordar mejor este problema. Sin embargo, esta es una solución que he estado usando y hasta ahora ha funcionado bien. Estoy usando sqlite, sin embargo, se puede modificar fácilmente para cualquiera de las bases de datos.
En resumen, este es el proceso:
- Agregar la nueva base de datos a la configuración (en tiempo de ejecución)
- Cree un archivo para almacenar estas configuraciones para volver a cargar cuando se reinicia el servidor (en tiempo de ejecución)
- Ejecute un script que carga los archivos de configuración guardados (siempre que se reinicia el servidor)
Ahora, cómo lograr esto:
1) En primer lugar, cuando se crea un nuevo usuario, creo una nueva base de datos en la configuración. Este código vive en mi opinión donde se crean nuevos usuarios.
from YOUR_PROJECT_NAME import settings
database_id = user.username #just something unique
newDatabase = {}
newDatabase["id"] = database_id
newDatabase[''ENGINE''] = ''django.db.backends.sqlite3''
newDatabase[''NAME''] = ''/path/to/db_%s.sql'' % database_id
newDatabase[''USER''] = ''''
newDatabase[''PASSWORD''] = ''''
newDatabase[''HOST''] = ''''
newDatabase[''PORT''] = ''''
settings.DATABASES[database_id] = newDatabase
save_db_settings_to_file(newDatabase) #this is for step 2)
Este script carga la configuración de la base de datos ''en tiempo de ejecución'' en la configuración del proyecto django. Sin embargo, si el servidor se reinicia, esta base de datos ya no estará en la configuración.
2) Para facilitar la recarga de estas configuraciones automáticamente cada vez que se reinicia el servidor, creo un archivo para cada base de datos que se cargará cada vez que se inicie el servidor. La creación de este archivo se realiza mediante la función save_db_settings_to_file
:
def save_db_settings_to_file(db_settings):
path_to_store_settings = "/path/to/your/project/YOUR_PROJECT_NAME/database_settings/"
newDbString = """
DATABASES[''%(id)s''] = {
''ENGINE'': ''%(ENGINE)s'', # Add ''postgresql_psycopg2'', ''mysql'', ''sqlite3'' or ''oracle''.
''NAME'': ''%(NAME)s'', # Or path to database file if using sqlite3.
''USER'': '''', # Not used with sqlite3.
''PASSWORD'': '''', # Not used with sqlite3.
''HOST'': '''', # Set to empty string for localhost. Not used with sqlite3.
''PORT'': '''', # Set to empty string for default. Not used with sqlite3.
}
""" % db_settings
file_to_store_settings = os.path.join(path_to_store_settings, db_settings[''id''] + ".py")
write_file(file_to_store_settings, newDbString) #psuedocode for compactness
3) Para cargar realmente esta configuración cuando se inicia el servidor, agrego una sola línea al final de /path/to/your/project/YOUR_PROJECT_NAME/settings.py
, que carga cada archivo en la carpeta de configuración y lo ejecuta. teniendo el efecto de cargar los detalles de la base de datos en la configuración.
import settings_manager
Luego, import settings_manager
cargará el archivo en /path/to/your/project/YOUR_PROJECT_NAME/settings_manager.py
, que contiene el siguiente código:
from settings import DATABASES
import os
path_to_store_settings = "/path/to/your/project/YOUR_PROJECT_NAME/database_settings/"
for fname in os.listdir(path_to_settings):
full_path = os.path.join(path_to_settings, fname)
f = open(full_path)
content = f.read()
f.close()
exec(content) #you''d better be sure that the file doesn''t contain anything malicious
Tenga en cuenta que puede colocar este código directamente en la parte inferior de settings.py en lugar de la declaración de importación, pero el uso de la declaración de importación mantiene el nivel de abstracción de settings.py consistente.
Esta es una forma conveniente de cargar cada configuración de la base de datos, ya que para eliminar una base de datos de la configuración, todo lo que tiene que hacer es eliminar el archivo de configuración, y la próxima vez que el servidor se reinicie no cargará esos detalles en la configuración, y la base de datos no será accesible.
Como dije, esto funciona y he tenido éxito usándolo hasta ahora, pero esta NO es la solución ideal. Realmente apreciaría si alguien pudiera publicar una mejor solución.
Lo que es malo al respecto:
- Desafía explícitamente el consejo del equipo de django de no modificar la configuración en tiempo de ejecución. No sé la razón por la que se da este consejo.
- Utiliza una declaración
exec
para cargar los datos en la configuración. Esto debería estar bien, pero si obtienes algún código corrupto o malicioso en uno de esos archivos, serás un panda triste.
Tenga en cuenta que todavía utilizo la base de datos predeterminada para datos de autenticación y sesiones, pero todos los datos de mis propias aplicaciones se almacenan en la base de datos específica del usuario.
He estado evaluando django y me pregunté si lo siguiente es posible. Ya he revisado los documentos de bases de datos múltiples regulares, así que, por favor, no me apuntes a eso porque este caso de uso no se menciona en la medida de lo posible. Si me equivoco me lo devuelvo :)
Quiero una base de datos principal en la que residirán la mayoría de los modelos de mi aplicación, sin embargo, una de las aplicaciones necesitará crear dinámicamente bases de datos, estas serán bases de datos específicas del cliente.
La ruta de la base de datos (planeo usar sqlite) se almacenará en la base de datos principal y, por lo tanto, será necesario cambiar el cursor pero el modelo seguirá siendo el mismo.
¿Agradecería cualquier pensamiento sobre maneras de lograr esto?
Para aumentar la respuesta de @thedawnrider, en algunos casos, la settings.DATABASES
edición. Las BASES DE DATOS pueden no ser suficientes. Podría ser más confiable editar django.db.connections.databases
, que sirve como caché y settings.DATABASES
alrededor de la settings.DATABASES
. django.db.connections.databases
.
p.ej
from django.db import connections
database_id = user.username #just something unique
newDatabase = {}
newDatabase["id"] = database_id
newDatabase[''ENGINE''] = ''django.db.backends.sqlite3''
newDatabase[''NAME''] = ''/path/to/db_%s.sql'' % database_id
newDatabase[''USER''] = ''''
newDatabase[''PASSWORD''] = ''''
newDatabase[''HOST''] = ''''
newDatabase[''PORT''] = ''''
connections.databases[database_id] = newDatabase