Je veux que l'implémentation de ma base de données se fasse dans un module ou une classe séparé. Mais je me heurte à quelques détails. Un exemple simple :
from peewee import *
db = SqliteDatabase(':memory:')
class BaseModel(Model):
class Meta:
database = db
class User(BaseModel):
name = CharField()
db.connect()
db.create_tables([User,])
db.commit()
@db.atomic()
def add_user(name):
User.create(name=name).save()
@db.atomic()
def get_user(name):
return User.get(User.name == name)
Jusqu'à présent, cela fonctionne bien. Je peux implémenter mon interface avec la base de données ici et l'importer en tant que module.
Maintenant, je veux pouvoir choisir le fichier de la base de données au moment de l'exécution. J'ai donc besoin d'un moyen de définir les classes du modèle sans définir les classes de la base de données. SqliteDatabase('somefile')
avant. J'ai essayé de tout encapsuler dans une nouvelle classe de base de données, que je peux ensuite importer et dont je peux créer une instance :
from peewee import *
class Database:
def __init__(self, dbfile):
self.db = SqliteDatabase(dbfile)
class BaseModel(Model):
class Meta:
database = self.db
class User(BaseModel):
name = CharField()
self.User = User
self.db.connect()
self.db.create_tables([User,])
self.db.commit()
@self.db.atomic() # Error as self is not known on this level
def add_user(self, name):
self.User.create(name=name).save()
@self.db.atomic() # Error as self is not known on this level
def get_user(self, name):
return self.User.get(self.User.name == name)
Maintenant je peux appeler par exemple database = Database('database.db')
ou choisir n'importe quel autre nom de fichier. Je peux même utiliser plusieurs instances de base de données dans le même programme, chacune ayant son propre fichier.
Toutefois, cette approche pose deux problèmes :
- Je dois encore spécifier le pilote de la base de données (
SqliteDatabase
) avant de définir les classes du modèle. Pour résoudre ce problème, je définis les classes de modèle dans la section__init__()
et ensuite créer un alias avecself.User = User
. Je n'aime pas vraiment cette approche (cela ne ressemble pas à du code soigné), mais au moins cela fonctionne. - Je ne peux pas utiliser le
@db.atomic()
depuis que le décorateurself
n'est pas connu au niveau de la classe, je voudrais un exemple ici.
Cette approche par classe ne semble donc pas fonctionner très bien. Existe-t-il un meilleur moyen de définir les classes du modèle sans avoir à choisir d'abord où vous voulez stocker votre base de données ?