Estoy diseñando una pequeña aplicación GUI para envolver una base de datos sqlite (operaciones CRUD simples). He creado tres modelos SQLAlchemy (m_person
, m_card.py
, m_loan.py
, todo en una carpeta /models
) y anteriormente había tenido el siguiente código en la parte superior de cada uno:¿Está bien ejecutar código cuando importa un módulo?
from sqlalchemy import Table, Column, create_engine
from sqlalchemy import Integer, ForeignKey, String, Unicode
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import backref, relation
engine = create_engine("sqlite:///devdata.db", echo=True)
declarative_base = declarative_base(engine)
metadata = declarative_base.metadata
esto se sentía un poco mal (SECO) por lo que se sugirió que moviera todas estas cosas al nivel de módulo (en models/__init__.py
).
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Table, Column, Boolean, Unicode
from settings import setup
engine = create_engine('sqlite:///' + setup.get_db_path(), echo=False)
declarative_base = declarative_base(engine)
metadata = declarative_base.metadata
session = sessionmaker()
session = session()
..y importar declarative_base
así:
from sqlalchemy import Table, Column, Unicode
from models import declarative_base
class Person(declarative_base):
"""
Person model
"""
__tablename__ = "people"
id = Column(Unicode(50), primary_key=True)
fname = Column(Unicode(50))
sname = Column(Unicode(50))
Sin embargo he tenido un montón de comentarios que la ejecución de código como las importaciones de módulos de este tipo es malo? Estoy buscando una respuesta definitiva en el camino correcto para hacerlo, ya que parece que al tratar de eliminar la repetición de código he introducido algunas otras malas prácticas. Cualquier comentario sería realmente útil.
(A continuación se muestra la get_db_path()
método de settings/setup.py
está completo como se le llama en el código models/__init__.py
anteriormente.)
def get_db_path():
import sys
from os import makedirs
from os.path import join, dirname, exists
from constants import DB_FILE, DB_FOLDER
if len(sys.argv) > 1:
db_path = sys.argv[1]
else:
#Check if application is running from exe or .py and adjust db path accordingly
if getattr(sys, 'frozen', False):
application_path = dirname(sys.executable)
db_path = join(application_path, DB_FOLDER, DB_FILE)
elif __file__:
application_path = dirname(__file__)
db_path = join(application_path, '..', DB_FOLDER, DB_FILE)
#Check db path exists and create it if not
def ensure_directory(db_path):
dir = dirname(db_path)
if not exists(dir):
makedirs(dir)
ensure_directory(db_path)
return db_path
Mi 2c, aunque generalmente está bien poner el código de inicio en '__init __. Py' (¡eso es lo que está ahí!), Yendo tan lejos como para establecer la URL de la base de datos, me parece erróneo. Puede hacer las pruebas más difíciles. Me parece que lo que debes hacer es tener una función 'init()' para el módulo. – cha0site
Creo que el problema aquí es que la clase base 'declarative_base' se crea dinámicamente y parece depender del motor de la base de datos. No sé cómo funciona sqlalchemy, pero ¿no es posible definir las clases de modelo antes de hacer la conexión de DB? Apenas puedo creer eso. –
@NiklasB. La 'declarative_base' depende de los" metadatos ", que es básicamente el motor core sqlalchemy. No necesariamente tiene vínculos con la base de datos, aunque puede optar por darle uno por simplicidad. – wberry