sessionmaker()
est une usine, elle est là pour encourager le placement des options de configuration pour créer de nouveaux Session
objets en un seul endroit. Il est facultatif, en ce sens que vous pouvez tout aussi facilement appeler Session(bind=engine, expire_on_commit=False)
chaque fois que vous avez besoin d'un nouveau Session
, sauf que c'est verbeux et redondant, et je voulais arrêter la prolifération des «assistants» à petite échelle qui ont chacun abordé la question de cette redondance dans une nouvelle et de manière plus déroutante.
C'est donc sessionmaker()
juste un outil pour vous aider à créer des Session
objets lorsque vous en avez besoin.
Partie suivante. Je pense que la question est de savoir quelle est la différence entre faire un nouveau Session()
à divers moments et simplement en utiliser un tout au long. La réponse, pas grand-chose. Session
est un conteneur pour tous les objets que vous y mettez, puis il garde également une trace d'une transaction ouverte. Au moment où vous appelez rollback()
ou commit()
, la transaction est terminée et le Session
n'a pas de connexion à la base de données jusqu'à ce qu'il soit appelé à émettre à nouveau SQL. Les liens qu'il détient vers vos objets mappés sont des références faibles, à condition que les objets soient exempts de modifications en attente, de sorte que même à cet égard, il Session
se videra dans un nouvel état lorsque votre application perdra toutes les références aux objets mappés. Si vous le laissez avec sa valeur par défaut"expire_on_commit"
, alors tous les objets ont expiré après une validation. Si cela Session
dure cinq ou vingt minutes et que toutes sortes de choses ont changé dans la base de données la prochaine fois que vous l'utiliserez, elle chargera tout nouvel état la prochaine fois que vous accéderez à ces objets même s'ils sont restés en mémoire pendant vingt minutes.
Dans les applications Web, nous disons généralement, pourquoi ne pas créer une nouvelle marque Session
à chaque demande, plutôt que d'utiliser la même chose encore et encore. Cette pratique garantit que la nouvelle demande commence «propre». Si certains objets de la requête précédente n'ont pas encore été récupérés, et si peut-être vous avez désactivé "expire_on_commit"
, peut-être qu'un état de la requête précédente est toujours en suspens, et cet état peut même être assez ancien. Si vous faites attention de laisser expire_on_commit
allumé et d'appeler définitivement commit()
ou rollback()
à la fin de la demande, alors c'est bien, mais si vous commencez avec un tout nouveau Session
, il n'y a même pas de question que vous commencez propre. Donc l'idée de commencer chaque demande avec un nouveauSession
est vraiment le moyen le plus simple de vous assurer que vous commencez à neuf et de rendre l'utilisation de expire_on_commit
presque facultative, car cet indicateur peut entraîner beaucoup de SQL supplémentaire pour une opération qui appelle commit()
au milieu d'une série d'opérations. Je ne sais pas si cela répond à votre question.
Le prochain tour est ce que vous mentionnez à propos du filetage. Si votre application est multithread, nous vous recommandons de vous assurer que l' Session
utilisation est locale à ... quelque chose. scoped_session()
par défaut le rend local au thread actuel. Dans une application Web, le local à la demande est en fait encore meilleur. Flask-SQLAlchemy envoie en fait une "fonction d'étendue" personnalisée à scoped_session()
afin que vous obteniez une session à portée de requête. L'application Pyramid moyenne colle la session dans le registre "request". Lorsque vous utilisez des schémas comme ceux-ci, l'idée «créer une nouvelle session sur demande de démarrage» continue de ressembler à la manière la plus simple de garder les choses en ordre.