sessionmaker()це фабрика, там можна заохочувати розміщення параметрів конфігурації для створення нових Sessionоб’єктів лише в одному місці. Це необов'язково, оскільки ви могли так само легко зателефонувати в Session(bind=engine, expire_on_commit=False)будь-який час, коли вам знадобилося новеSession , за винятком того, що його багатослівний і зайвий, і я хотів зупинити розповсюдження дрібних "помічників", які кожен підходив до проблеми цієї надмірності в деяких нових і більш заплутаний спосіб.
Отже, sessionmaker()це лише інструмент, який допоможе вам створити Sessionоб’єкти, коли вони вам потрібні.
Наступна частина. Я думаю, що питання полягає в тому, яка різниця між створенням нового Session()в різних точках, а не просто використанням одного до кінця. Відповідь, не дуже. Sessionє контейнером для всіх об'єктів, які ви вкладаєте в нього, а потім він також відстежує відкриту транзакцію. У той момент, коли ви дзвоните rollback()або commit(), транзакція закінчена, і Sessionне має зв'язку з базою даних, поки не буде покликано знову випромінювати SQL. Посилання, які він тримає до ваших відображених об’єктів, є слабкими посиланнями, за умови, що об'єкти чисті від очікуючих змін, тому навіть у зв'язку з цим налаштуванням всі об'єкти закінчуються після фіксації. Якщо цеSession воля випорожниться назад до абсолютно нового стану, коли ваша програма втратить усі посилання на відображені об’єкти. Якщо залишити його за замовчуванням"expire_on_commit"Sessionзависає протягом п’яти-двадцяти хвилин, і всі види речей змінилися в базі даних наступного разу, коли ви будете використовувати її, вона завантажить абсолютно новий стан наступного разу, коли ви отримаєте доступ до цих об'єктів, навіть якщо вони сидять у пам'яті двадцять хвилин.
У веб-додатках ми, як правило, кажемо, ей, чому б вам не зробити новенький Sessionна кожен запит, а не використовувати один і той же раз і знову. Ця практика гарантує, що новий запит починається "чисто". Якщо деякі об'єкти з попереднього запиту ще не були зібрані сміттям, і якщо, можливо, ви його вимкнули "expire_on_commit", можливо, якийсь стан із попереднього запиту все ще зависає, і цей стан може бути навіть досить старим. Якщо ви обережно залишаєте expire_on_commitувімкненим і обов'язково зателефонували commit()або rollback()на запит закінчились, тоді це добре, але якщо ви почнете з абсолютно нового Session, тоді навіть не виникає жодних питань, з якими ви починаєте чисто. Тож ідея починати кожен запит з новогоSessionнасправді просто найпростіший спосіб переконатися, що ви починаєте свіжим, і використовувати його в середині серії операцій. Не впевнений, чи відповідає це на ваше запитання.expire_on_commit майже необов'язковим, оскільки цей прапор може спричинити багато додаткового SQL для операції, яка викликаєcommit()
Наступний раунд - це те, що ви згадуєте про нарізування різьби. Якщо ваш додаток багатопотокове, радимо переконатися, що Sessionвикористання використовується локальним для чогось. scoped_session()за замовчуванням робить його локальним для поточного потоку. У веб-додатку локальний запит насправді ще кращий. Flask-SQLAlchemy насправді надсилає користувацьку "функцію діапазону", щоб scoped_session()ви отримали сеанс, що охоплює запит. Середня програма Pyramid вписує Сесію в реєстр "запитів". Використовуючи подібні схеми, ідея "створити нову сесію під час запиту" продовжує виглядати як найпростіший спосіб зробити все прямо.