{"id":381921,"date":"2024-06-29T03:57:38","date_gmt":"2024-06-29T03:57:38","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=381921"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2024-06-29T03:57:38","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=381921","title":{"rendered":"<span>SQL \u0432 SQLAlchemy<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0410\u043b\u0435\u043a\u0441\u0435\u0439 \u041a\u0430\u0437\u0430\u043a\u043e\u0432, \u044f \u0442\u0435\u0445\u043b\u0438\u0434 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0435 \u043a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u0438\u00bb \u0432 \u0414\u043e\u043c\u043a\u043b\u0438\u043a. \u041f\u043e \u043c\u043e\u0435\u043c\u0443 \u043e\u043f\u044b\u0442\u0443 \u043f\u043e\u0434\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0435 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e Object Relational Mapper. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0443 \u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c \u0432\u0430\u0441 \u0441 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u043c\u0438 ORM, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u043b\u0438\u0441\u044c \u043c\u043d\u0435 \u0432 \u043f\u0440\u043e\u0434\u043e\u0432\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445. \u0412 <a href=\"https:\/\/habr.com\/ru\/company\/domclick\/blog\/552930\/\">\u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437<\/a> \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u043b\u0438 Django ORM , \u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043d\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0432\u0441\u0435\u043c\u043e\u0433\u0443\u0449\u0438\u0439 <a href=\"https:\/\/www.sqlalchemy.org\/\">SQLAlchemy<\/a>.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/433\/2bf\/981\/4332bf981d4fe5ca56ad3e026347911d.png\" width=\"2310\" height=\"1502\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/433\/2bf\/981\/4332bf981d4fe5ca56ad3e026347911d.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0411\u0443\u0434\u0435\u043c \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u043d\u0430:<\/p>\n<ul>\n<li>\n<p>\u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0441\u0445\u0435\u043c\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 (\u0441\u044b\u0440\u043e\u0439 SQL);<\/p>\n<\/li>\n<li>\n<p>\u043e\u043f\u0438\u0448\u0435\u043c \u044d\u0442\u0443 \u0441\u0445\u0435\u043c\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e alchemy-\u043c\u043e\u0434\u0435\u043b\u0435\u0439;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043c\u0441\u044f \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0445\u0438\u0442\u0440\u043e\u0441\u0442\u044f\u043c\u0438 \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u043e\u0442\u043b\u0430\u0434\u043a\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0430 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0438\u0437\u0443\u0447\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0441\u043e\u0431\u043e\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0443\u0434\u0435\u043b\u0438\u043c \u0441\u044b\u0440\u043e\u043c\u0443 SQL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430. \u0412\u0435\u0434\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u043e\u0442 \u043d\u0435\u0433\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<h2>\u0421\u0445\u0435\u043c\u0430<\/h2>\n<p>\u0421\u0445\u0435\u043c\u0443 \u043c\u044b \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u043d\u043e\u0439 \u043d\u0430 \u043f\u0440\u043e\u0442\u044f\u0436\u0435\u043d\u0438\u0438 \u0432\u0441\u0435\u0445 \u0441\u0442\u0430\u0442\u0435\u0439. \u041f\u0443\u0441\u0442\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 (User) \u043c\u043e\u0433\u0443\u0442 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u043e\u043f\u0440\u043e\u0441\u044b (Question) \u0432\u043d\u0443\u0442\u0440\u0438 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0435\u043c (Topic). \u0423 \u0442\u043e\u043f\u0438\u043a\u0430 \u0435\u0441\u0442\u044c \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430 (Image). \u0414\u043e\u0441\u0442\u0443\u043f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043a \u0442\u043e\u043f\u0438\u043a\u0443 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 many-to-many \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 TopicUser, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043a\u0440\u043e\u043c\u0435 ForeignKey (FK) \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 FK \u0434\u043b\u044f \u0442\u043e\u043f\u0438\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u2014 \u0440\u043e\u043b\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u0442\u043e\u043f\u0438\u043a\u0435.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2d6\/754\/6f2\/2d67546f2bfc7b1aff3405ff83cd5e63.png\" width=\"1409\" height=\"1600\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2d6\/754\/6f2\/2d67546f2bfc7b1aff3405ff83cd5e63.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0438\u043c SQL-\u0435\u043c:<\/p>\n<pre><code class=\"sql\">CREATE TABLE \"image\" (     \"id\"   serial NOT NULL PRIMARY KEY,     \"name\" text   NOT NULL );  CREATE TABLE \"topic\" (     \"id\"       serial  NOT NULL PRIMARY KEY,     \"title\"    text    NOT NULL,     \"image_id\" integer REFERENCES \"image\" (\"id\") NOT NULL );  CREATE TABLE \"user\" (     \"id\"   serial NOT NULL PRIMARY KEY,     \"name\" text   NOT NULL );  CREATE TABLE \"topic_user\" (     \"id\"       serial  NOT NULL PRIMARY KEY,     \"role\"     text    NOT NULL,     \"topic_id\" integer REFERENCES \"topic\" (\"id\") NOT NULL,     \"user_id\"  integer REFERENCES \"user\" (\"id\") NOT NULL );  CREATE TABLE \"question\" (     \"id\"       serial  NOT NULL PRIMARY KEY,     \"text\"     text    NOT NULL,     \"topic_id\" integer REFERENCES \"topic\" (\"id\") NOT NULL  );<\/code><\/pre>\n<h2>Alchemy models<\/h2>\n<p>\u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c SQL-\u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0432 \u043d\u0430\u0448\u0435\u043c Python-\u043a\u043e\u0434\u0435, \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439. \u041e\u0431\u044b\u0447\u043d\u043e \u0435\u0433\u043e \u043d\u0430\u0437\u044b\u0432\u0430\u044e\u0442 <code>Base<\/code>, \u0438 \u0432\u0441\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u044e\u0442 \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430. \u042d\u0442\u043e\u0442 declarative base class \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a \u0432\u0441\u0435\u0445 \u00ab\u0441\u0432\u043e\u0438\u0445\u00bb \u0442\u0430\u0431\u043b\u0438\u0446 \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0435\u043c\u0443 \u043a\u043b\u0430\u0441\u0441\u043e\u0432. \u041e\u0431\u044b\u0447\u043d\u043e <code>Base<\/code> \u043e\u0434\u0438\u043d \u043d\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0435\u0433\u043e \u0437\u0430\u0432\u043e\u0434\u044f\u0442 \u0432 \u043e\u0431\u0449\u0435\u043c \u043c\u043e\u0434\u0443\u043b\u0435. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0440\u0430\u0437\u043d\u044b\u0445 \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0440\u0430\u0437\u043d\u044b\u043c \u0431\u0430\u0437\u0430\u043c \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">from sqlalchemy.ext.declarative import declarative_base  Base = declarative_base()   class Image(Base):     __tablename__ = 'image'      id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)     name = sa.Column(sa.Text, nullable=False)   class Topic(Base):     __tablename__ = 'topic'      id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)     title = sa.Column(sa.Text, nullable=False)     image_id = sa.Column(sa.Integer, sa.ForeignKey('image.id'), nullable=False)     image = sa.orm.relationship(Image)  # innerjoin=True \u0434\u043b\u044f JOIN     questions = sa.orm.relationship('Question')      users = sa.orm.relationship('User', secondary='topic_user')     # association     # users = sa.orm.relationship('TopicUser', back_populates='topic')   class User(Base):     __tablename__ = 'user'      id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)     name = sa.Column(sa.Text, nullable=False)      # association     # topics = sa.orm.relationship('TopicUser', back_populates='user')   class TopicUser(Base):     __tablename__ = 'topic_user'      id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)     topic_id = sa.Column(sa.Integer, sa.ForeignKey('topic.id'))     user_id = sa.Column(sa.Integer, sa.ForeignKey('user.id'))     role = sa.Column(sa.Text)      # association     # user = sa.orm.relationship(User, back_populates='topics')     # topic = sa.orm.relationship(Topic, back_populates='users')   class Question(Base):     __tablename__ = 'question'      id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)     text = sa.Column(sa.Text)     topic_id = sa.Column(sa.Integer, sa.ForeignKey('topic.id'), nullable=False)     topic = sa.orm.relationship(Topic)  # innerjoin=True \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f JOIN \u0432\u043c\u0435\u0441\u0442\u043e LEFT JOIN <\/code><\/pre>\n<\/div>\n<\/details>\n<h2>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430<\/h2>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0431\u0430\u0437\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0432\u0438\u0436\u043a\u0430, \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f. \u0422\u0430\u043a\u0436\u0435 \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>echo=True<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u0432\u0438\u0434\u0435\u0442\u044c \u0432\u0441\u0435 \u0442\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0430\u043b\u0445\u0438\u043c\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437 \u043d\u0430\u0448\u0435\u0433\u043e Python-\u043a\u043e\u0434\u0430 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0432 \u0411\u0414.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0441\u0435\u0441\u0441\u0438\u0439. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u043c\u0443 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0443 \u0432\u0441\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0435 \u0432 \u043d\u0435\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u0435\u0441\u0441\u0438\u044f \u0431\u0443\u0434\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u043a\u043e\u043c\u043c\u0438\u0442\u0438\u0442\u044c, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0431\u044b\u043b\u043e \u043e\u0448\u0438\u0431\u043e\u043a \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u043a\u0430\u0442\u044b\u0432\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e \u0441\u0435\u0441\u0441\u0438\u0438 \u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438 \u043f\u043e \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c <a href=\"https:\/\/docs.sqlalchemy.org\/en\/14\/orm\/session_basics.html#session-faq-whentocreate\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">from contextlib import contextmanager  import sqlalchemy as sa from sqlalchemy.orm import sessionmaker  main_engine = sa.create_engine(     'postgres:\/\/localhost:5432\/habr_sql?sslmode=disable',     echo=True, )  DBSession = sessionmaker(     binds={         Base: main_engine,     },     expire_on_commit=False, )   @contextmanager def session_scope():     \"\"\"Provides a transactional scope around a series of operations.\"\"\"     session = DBSession()     try:         yield session         session.commit()     except Exception as e:         session.rollback()         raise e     finally:         session.close()  if __name__ == '__main__':     with session_scope() as s:         &lt;actual_code><\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0445 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043e\u0432 \u043a\u043e\u0434\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0432\u0441\u0435\u0445 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432. \u041d\u0430\u043f\u043e\u043c\u043d\u044e, \u0447\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0432 \u0441\u0442\u0430\u0442\u044c\u044f\u0445 \u0441\u043a\u0432\u043e\u0437\u043d\u044b\u0435, \u0442\u043e \u0435\u0441\u0442\u044c \u00ab\u041f\u0440\u0438\u043c\u0435\u0440 n\u00bb \u0432 \u043b\u044e\u0431\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e \u043e\u0434\u043d\u043e \u0438 \u0442\u043e \u0436\u0435.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 1<\/h4>\n<p>\u0425\u043e\u0442\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u0435\u0441\u044f\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u0438\u0437 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u043e\u043f\u0438\u043a\u0430.<\/p>\n<pre><code class=\"sql\">SELECT * FROM question WHERE topic_id = 1 ORDER BY id DESC LIMIT 10;<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u0430\u043b\u0445\u0438\u043c\u0438\u0438:<\/p>\n<pre><code class=\"python\">questions = s.query(Question).filter(     Question.topic_id == t1_id, ).order_by(Question.id.desc()).limit(10).all()<\/code><\/pre>\n<p>\u0421\u0440\u0430\u0437\u0443 \u0443\u0447\u0438\u043c\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c\u0443 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0443 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a \u043f\u043e\u043b\u044f\u043c \u043a\u043b\u0430\u0441\u0441\u0430. \u0412 Django \u0438\u043d\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434: \u0432 <code>filter<\/code> \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u043f\u043e \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043d\u043e\u043c\u0443 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0443, \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u043c\u0443 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u0432 \u0431\u0430\u0437\u0435. \u0417\u0434\u0435\u0441\u044c \u0436\u0435 \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 <code>Question.topic_id == t1_id<\/code> \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u0435\u0440\u0435\u0434\u0430\u0441\u0442\u0441\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 <code>BinaryExpression<\/code>.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 2<\/h4>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043d\u0430\u0439\u0442\u0438 \u0442\u0430\u043a\u0438\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0442\u043e\u043f\u0438\u043a\u0430, \u0432 \u0442\u0435\u043a\u0441\u0442\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043b\u0438\u0431\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u043f\u043e\u0434\u0441\u0442\u0440\u043e\u043a\u0430 <code>fart<\/code>, \u043b\u0438\u0431\u043e \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u044f <code>dog<\/code>, \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0438\u0445 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430. \u041c\u044b \u043b\u0435\u0433\u043a\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0437\u0438\u043c \u044d\u0442\u043e \u043d\u0430 SQL:<\/p>\n<pre><code class=\"sql\">SELECT * FROM question WHERE (   topic_id = 1 AND (       text ILIKE '%fart%' OR       NOT (text ILIKE '%dog%')   ) );<\/code><\/pre>\n<p>\u0412 \u0430\u043b\u0445\u0438\u043c\u0438\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 Django-\u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u044f \u0432\u0438\u0436\u0443 \u043b\u0438\u0448\u044c \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u00ab\u0438\u043b\u0438\u00bb:<\/p>\n<pre><code class=\"python\">questions = s.query(Question).filter(     Question.topic_id == 1,     sa.or_(Question.text.ilike('%fart%'), ~Question.text.ilike('%dog%')) )  for q in questions:     print(q.id)<\/code><\/pre>\n<p>\u0412 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0443\u0432\u0438\u0434\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 SQL-\u0437\u0430\u043f\u0440\u043e\u0441:<\/p>\n<pre><code class=\"sql\">SELECT question.id AS question_id, question.text AS question_text, question.topic_id AS question_topic_id  FROM question  WHERE question.topic_id = %(topic_id_1)s AND (   question.text ILIKE %(text_1)s OR question.text NOT ILIKE %(text_2)s )<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0437\u0430\u043f\u0440\u043e\u0441 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0441\u044f \u0432 \u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043d\u0430\u0447\u043d\u0435\u043c \u0438\u0442\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e <code>questions<\/code>. \u0414\u043e \u044d\u0442\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u0431\u0430\u0437\u0443 \u043d\u0435 \u0443\u0445\u043e\u0434\u0438\u043b\u043e, \u0430 \u0432 <code>questions<\/code> \u043b\u0435\u0436\u0430\u043b \u043e\u0431\u044a\u0435\u043a\u0442 <code>Query<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0435\u0449\u0451 \u043a\u0430\u043a-\u0442\u043e \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0434\u043e\u0431\u0430\u0432\u0438\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043b\u0438\u043c\u0438\u0442. \u041f\u043e\u0445\u043e\u0436\u0435\u0435 \u043c\u044b \u0432\u0438\u0434\u0435\u043b\u0438 \u0438 \u0432 Django. \u042d\u0442\u043e \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043b\u0435\u043d\u0438\u0432\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 (lazy loading).<\/p>\n<p>\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 Python-\u043a\u043e\u0434\u0430:<\/p>\n<pre><code class=\"python\">questions = s.query(Question).filter(   (Question.topic_id == 1) &amp;   (Question.text.ilike('%fart%') | ~Question.text.ilike('%dog%')) )<\/code><\/pre>\n<p>&#8230;\u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 3<\/h4>\n<p>\u042d\u0442\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u0434\u0432\u043e\u0434\u0438\u0442 \u043d\u0430\u0441 \u043a \u0442\u0435\u043c\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0430\u043c\u043e\u0433\u043e \u0432\u043e\u043f\u0440\u043e\u0441\u0430, \u043d\u043e \u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0441 \u043d\u0438\u043c \u0442\u043e\u043f\u0438\u043a\u0430. \u0412 \u0430\u043b\u0445\u0438\u043c\u0438\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u0445\u043e\u0436\u0438\u0439 \u043f\u0440\u0438\u043d\u0446\u0438\u043f. \u0420\u0430\u0431\u043e\u0442\u0430 \u00ab\u0432 \u043b\u043e\u0431\u00bb:<\/p>\n<pre><code class=\"python\">q = s.query(Question).filter(Question.id == 1).first()  # sa.3.1 print(q.topic.title)  # sa.3.2<\/code><\/pre>\n<p>&#8230;\u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u0442\u043e\u043c\u0443 \u0447\u0442\u043e, <code>sa.3.1<\/code> \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0437\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c, \u0430 <code>sa.3.2<\/code> \u2014 \u0437\u0430 \u0442\u043e\u043f\u0438\u043a\u043e\u043c. \u0427\u0442\u043e\u0431\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432 \u0431\u0430\u0437\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0437\u0430\u043f\u0440\u043e\u0441, \u043d\u0443\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u043f\u0446\u0438\u044f\u043c\u0438:<\/p>\n<pre><code class=\"python\">q = s.query(Question).filter(     Question.id == 1, ).options(joinedload(Question.topic)).first() print(q.topic.title)<\/code><\/pre>\n<p>\u0412 \u0430\u043b\u0445\u0438\u043c\u0438\u0438 \u044d\u0442\u043e\u0442 \u043f\u043e\u0434\u0445\u043e\u0434 \u043d\u043e\u0441\u0438\u0442 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 Eager Loading, \u0432\u043e\u0442 <a href=\"https:\/\/docs.sqlalchemy.org\/en\/13\/orm\/tutorial.html#eager-loading\">\u0441\u0441\u044b\u043b\u043a\u0430<\/a> \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u044b. \u041e\u043f\u0446\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043d\u043e \u0438 \u043f\u0440\u0438 <a href=\"https:\/\/docs.sqlalchemy.org\/en\/13\/orm\/loading_relationships.html\">\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043c\u043e\u0434\u0435\u043b\u0438<\/a>. \u041d\u043e \u043c\u043d\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u043f\u0446\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u0440\u0438 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 SQL \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0430\u0448\u0438\u043c \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f\u043c. \u0421\u043e\u0432\u0435\u0442\u0443\u044e \u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a \u043f\u0440\u0438 \u043b\u044e\u0431\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0435 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0412\u0440\u0435\u043c\u0435\u043d\u0438 \u044d\u0442\u043e \u0437\u0430\u0439\u043c\u0451\u0442 \u043f\u0430\u0440\u0443 \u043c\u0438\u043d\u0443\u0442, \u0437\u0430\u0442\u043e \u043f\u0440\u0438\u0434\u0430\u0441\u0442 \u0432\u0430\u043c \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0438 \u0441\u043f\u0430\u0441\u0451\u0442 \u043e\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e.<\/p>\n<pre><code class=\"sql\">SELECT question.id       AS question_id,        question.text     AS quetion_text,        question.topic_id AS question_topic_id,        topic_1.id        AS topic_1_id,        topic_1.title     AS topic_1_title,        topic_1.image_id  AS topic_1_image_id FROM question          LEFT OUTER JOIN topic AS topic_1 ON topic_1.id = question.topic_id WHERE question.id = %(id_1)s LIMIT %(param_1)s;<\/code><\/pre>\n<p>\u0412\u0441\u0451 \u043d\u0435\u043f\u043b\u043e\u0445\u043e, \u0432\u0435\u0434\u044c \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0442\u043e\u043f\u0438\u043a\u0430 \u0438 \u043d\u0435 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0445\u043e\u0434\u0438\u0442\u044c \u0432 \u0431\u0430\u0437\u0443. \u041d\u043e <code>LEFT JOIN<\/code> \u0432 \u043d\u0430\u0448\u0435\u0439 \u0441\u0445\u0435\u043c\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437\u043b\u0438\u0448\u0435\u043d, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u043e\u043f\u0440\u043e\u0441\u0430, \u043d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u043a \u0442\u043e\u043f\u0438\u043a\u0443. \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u043b\u0445\u0438\u043c\u0438\u0438 \u043f\u0440\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0438 relation-\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e <code>INNER JOIN<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u0435\u043d, \u0447\u0435\u043c <code>OUTER<\/code>:<\/p>\n<pre><code class=\"python\">topic = sa.orm.relationship(Topic, innerjoin=True)<\/code><\/pre>\n<p>\u0421 \u0442\u0430\u043a\u0438\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0447\u0435\u0441\u0442\u043d\u044b\u0439 <code>INNER JOIN<\/code>.<\/p>\n<p>\u0415\u0441\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u043d\u0430 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0430\u043b\u0445\u0438\u043c\u0438\u0438. \u041a\u0430\u043a \u044f \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u00ab\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430\u00bb, \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0441\u0435\u0441\u0441\u0438\u0438. \u041d\u043e \u0435\u0441\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043d\u0435\u0441\u0435\u043d \u0437\u0430 \u0441\u0435\u0441\u0441\u0438\u044e, \u0442\u043e \u0434\u043b\u044f \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043c\u044b \u043f\u043e\u0442\u0435\u0440\u044f\u0435\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u00ab\u043f\u043e\u0434\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0430 \u043b\u0435\u0442\u0443\u00bb. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"python\">with session_scope() as s:     q = s.query(Question).filter(Question.id == 1).first() print(q.topic.title) # sqlalchemy.orm.exc.DetachedInstanceError: Parent instance &lt;Question at 0x109dde470> is not bound to a Session; lazy load operation of attribute 'topic' cannot proceed<\/code><\/pre>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 4<\/h4>\n<p>\u042d\u0442\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440 \u0443\u0433\u043b\u0443\u0431\u0438\u0442 \u043d\u0430\u0448\u0438 \u0437\u043d\u0430\u043d\u0438\u044f \u043f\u043e \u0442\u0435\u0445\u043d\u0438\u043a\u0435 \u043d\u0435\u0442\u0435\u0440\u043f\u0435\u043b\u0438\u0432\u043e\u0439 \u043f\u043e\u0434\u0433\u0440\u0443\u0437\u043a\u0438. \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0441 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c \u0442\u043e\u043f\u0438\u043a, \u043d\u043e \u0435\u0449\u0451 \u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u0442\u043e\u043f\u0438\u043a\u0430. \u0412 \u0430\u043b\u0445\u0438\u043c\u0438\u0438 (\u0435\u0441\u043b\u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u0440\u0430\u0431\u043e\u0442\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0441\u0441\u0438\u0438) \u00ab\u043c\u0430\u0433\u0438\u044f\u00bb \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430. \u041d\u0430\u043f\u043e\u043c\u043d\u044e, \u0447\u0442\u043e \u043f\u043e\u0445\u043e\u0436\u0443\u044e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e \u043c\u044b \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u043b\u0438 \u0438 \u0432 Django.<\/p>\n<pre><code class=\"python\">with session_scope() as s:     for q in s.query(Question).filter(Question.topic_id == 1).all():  # sa.4.1         print(q.topic.title)  # sa.4.2         print(q.topic.image.name)  # sa.4.3<\/code><\/pre>\n<p>\u041e\u0436\u0438\u0434\u0430\u0435\u043c\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0437\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u0432 <code>sa.4.1<\/code>. \u041f\u0440\u0438 \u0438\u0442\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c \u0432 Django, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438\u0437 \u0431\u0430\u0437\u044b \u043a\u0435\u0448\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 \u0441\u0435\u0441\u0441\u0438\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u043f\u0440\u043e\u0445\u043e\u0434\u0435 \u0446\u0438\u043a\u043b\u0430 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0434\u0432\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430:<\/p>\n<ul>\n<li>\n<p><code>sa.4.2<\/code> \u2014 \u0437\u0430 \u0442\u043e\u043f\u0438\u043a\u043e\u043c;<\/p>\n<\/li>\n<li>\n<p><code>sa.4.3<\/code> \u2014 \u0437\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c. <\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u043e \u043d\u0430 \u0432\u0442\u043e\u0440\u043e\u043c \u043f\u0440\u043e\u0445\u043e\u0434\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0442\u043e\u043f\u0438\u043a \u0438 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430 \u0437\u0430\u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u0432 \u0441\u0435\u0441\u0441\u0438\u0438. \u041e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e \u043d\u0435 \u0441\u043f\u0430\u0441\u0451\u0442, \u0435\u0441\u043b\u0438 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u044c\u0441\u044f \u043a \u0440\u0430\u0437\u043d\u044b\u043c \u0442\u043e\u043f\u0438\u043a\u0430\u043c.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u044f\u0432\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0430\u043b\u0445\u0438\u043c\u0438\u044e \u0437\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u043d\u0435\u0442\u0435\u0440\u043f\u0435\u043b\u0438\u0432\u043e\u0439 \u043f\u043e\u0434\u0433\u0440\u0443\u0437\u043a\u043e\u0439, \u0441\u043d\u043e\u0432\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043e\u043f\u0446\u0438\u0438. \u041d\u0430 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u0434\u0432\u0435:<\/p>\n<pre><code class=\"python\">with session_scope() as s:     for q in s.query(Question).options(         joinedload('topic'),         joinedload('topic.image'),     ).filter(Question.topic_id == 1).all():  # sa.4.4         print(q.topic.title)  # sa.4.5         print(q.topic.image.name)  # sa.4.6<\/code><\/pre>\n<p>\u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0442\u043e\u043b\u044c\u043a\u043e <code>sa.3.4<\/code> \u0441\u043f\u0440\u043e\u0432\u043e\u0446\u0438\u0440\u0443\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 \u0431\u0430\u0437\u0443.<\/p>\n<pre><code class=\"sql\">SELECT question.id       AS question_id,        question.text     AS question_text,        question.topic_id AS question_topic_id,        image_1.id        AS image_1_id,        image_1.name      AS image_1_name,        topic_1.id        AS topic_1_id,        topic_1.title     AS topic_1_title,        topic_1.image_id  AS topic_1_image_id FROM question          JOIN topic AS topic_1 ON topic_1.id = question.topic_id          LEFT OUTER JOIN image AS image_1 ON image_1.id = topic_1.image_id WHERE question.topic_id = %(topic_id_1)s<\/code><\/pre>\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 join \u2014 <code>LEFT OUTER JOIN<\/code>. \u0415\u0441\u043b\u0438 \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d <code>INNER JOIN<\/code>, \u0442\u043e \u043c\u044b \u0443\u0436\u0435 \u0437\u043d\u0430\u0435\u043c, \u043a\u0430\u043a \u043d\u0443\u0436\u043d\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c: <code>image = sa.orm.relationship(Image, innerjoin=True)<\/code>.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 5<\/h4>\n<p>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432\u0441\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u043e\u043f\u0438\u043a\u0430. \u041a\u0430\u043a \u0438 \u0432 Django, \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0441 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0435\u0439. \u0422\u0430\u043a \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0435, \u043d\u043e \u043d\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"python\">for t in s.query(Topic).filter(Topic.id.in_([1, 2])).all():  # sa.5.1     print([q.text for q in t.questions])  # sa.5.2<\/code><\/pre>\n<ul>\n<li>\n<p><code>sa.5.1<\/code> \u2014 \u0437\u0430\u043f\u0440\u043e\u0441 \u0437\u0430 \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u0442\u043e\u043f\u0438\u043a\u043e\u0432;<\/p>\n<\/li>\n<li>\n<p><code>sa.5.2<\/code> \u2014 N \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0437\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u0448\u0430\u0433\u0435 \u0446\u0438\u043a\u043b\u0430 \u043f\u043e \u0442\u043e\u043f\u0438\u043a\u0430\u043c.<\/p>\n<\/li>\n<\/ul>\n<p>\u0423\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u0435 \u0441\u043d\u043e\u0432\u0430 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043e\u043f\u0446\u0438\u0439.<\/p>\n<pre><code class=\"python\">for t in s.query(Topic).options(joinedload('questions')).filter(Topic.id.in_([1, 2])).all():     print([q.text for q in t.questions])<\/code><\/pre>\n<p>\u0418 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 Django, \u0433\u0434\u0435 \u0438\u0445 \u0431\u044b\u043b\u043e \u0434\u0432\u0430. \u0412 \u0447\u0451\u043c \u0440\u0430\u0437\u043d\u0438\u0446\u0430? \u0417\u0434\u0435\u0441\u044c \u043e\u0434\u0438\u043d \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0441 <code>LEFT OUTER JOIN<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u0438\u0442\u043e\u0433\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0442\u043e\u043c\u0443 \u0436\u0435 \u0441\u0430\u043c\u043e\u043c\u0443.<\/p>\n<pre><code>SELECT topic.id            AS topic_id,        topic.title         AS topic_title,        topic.image_id      AS topic_image_id,        question_1.id       AS question_1_id,        question_1.text     AS question_1_text,        question_1.topic_id AS question_1_topic_id FROM topic          LEFT OUTER JOIN question AS question_1 ON topic.id = question_1.topic_id WHERE topic.id IN (%(id_1)s, %(id_2)s) <\/code><\/pre>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0440\u0443\u0433\u043e\u0439 \u043e\u043f\u0446\u0438\u0438: <code>subqueryload<\/code>. \u041d\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 Django. \u0414\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u0442\u043e\u043f\u0438\u043a\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u043f\u0435\u0440\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432\u043c\u0435\u0441\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0441 \u044d\u0442\u0438\u043c\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 6<\/h4>\n<p>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043a \u0442\u043e\u043f\u0438\u043a\u0443 \u043d\u0435 \u0432\u0441\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b, \u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c\u0443 \u0443\u0441\u043b\u043e\u0432\u0438\u044e. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0443 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u043e\u043f\u0438\u043a\u043e\u0432 \u043c\u043e\u0436\u0435\u0442 \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p>\u0412 \u0430\u043b\u0445\u0438\u043c\u0438\u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0430\u0441\u0441\u0438\u0432 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u043e\u0432\u043e\u0439 \u043e\u043f\u0446\u0438\u0438 \u0438 \u0430\u043b\u0438\u0430\u0441\u0430, \u0447\u0442\u043e \u0432 \u0441\u043e\u0432\u043e\u043a\u0443\u043f\u043d\u043e\u0441\u0442\u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0435 \u0441\u0430\u043c\u044b\u043c \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c.<\/p>\n<pre><code class=\"python\">q_stmt = s.query(Question).filter(Question.text.ilike('%fart%')).subquery()  # sa.6.1 alias = aliased(Question, q_stmt)  # sa.6.2  filtered_topics = s.query(Topic).outerjoin(  # sa.6.3     Topic.questions.of_type(alias),  # sa.6.4     ).options(     contains_eager(Topic.questions.of_type(alias)),  # sa.6.5 )  for t in filtered_topics:     print(f'{t.title}')     for q in t.questions:         print(f' --- {q.text}')<\/code><\/pre>\n<ul>\n<li>\n<p><code>sa.6.1<\/code>: \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441, \u0432\u044b\u0431\u0438\u0440\u0430\u044e\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0449\u0438\u0435 \u043d\u0430\u0441 \u0432\u043e\u043f\u0440\u043e\u0441\u044b. \u0412 \u0431\u0430\u0437\u0443 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0435\u0449\u0435 \u043d\u0435 \u0443\u0445\u043e\u0434\u0438\u0442.<\/p>\n<\/li>\n<li>\n<p><code>sa.6.2<\/code>: \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0430\u043b\u0438\u0430\u0441. \u041e\u043d\u0438 \u043e\u0431\u044b\u0447\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f <code>SELF JOIN<\/code>-\u0430 \u0438\u043b\u0438 \u0434\u043b\u044f \u0437\u0430\u043c\u0435\u043d\u044b \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u043c \u0435\u0451 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p><code>sa.6.3<\/code>: \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>LEFT OUTER JOIN<\/code>.<\/p>\n<\/li>\n<li>\n<p><code>sa.6.4<\/code>: \u0437\u0430 \u0441\u0447\u0435\u0442 <code>of_type<\/code> \u043c\u044b \u0434\u0436\u043e\u0439\u043d\u0438\u043c \u043d\u0435 \u0441 \u0446\u0435\u043b\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\u0439, \u0430 \u0441 \u0442\u0435\u043c \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d.<\/p>\n<\/li>\n<li>\n<p><code>sa.6.5<\/code>: \u043f\u0440\u043e\u0441\u0438\u043c \u0432 <code>Topic.questions<\/code> \u043f\u043e\u0434\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043d\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c, \u0430 \u0443\u0436\u0435 \u0438\u0437 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043d\u0430\u043c\u0438 \u043a\u043e\u043b\u043e\u043d\u043e\u043a. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u0441\u043c. <a href=\"https:\/\/docs.sqlalchemy.org\/en\/13\/orm\/loading_relationships.html#sqlalchemy.orm.contains_eager\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u043e\u0442 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 <a href=\"https:\/\/docs.sqlalchemy.org\/en\/13\/orm\/loading_relationships.html#routing-explicit-joins-statements-into-eagerly-loaded-collections\">\u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>:<\/p>\n<pre><code class=\"sql\">SELECT anon_1.id       AS anon_1_id,        anon_1.text     AS anon_1_text,        anon_1.topic_id AS anon_1_topic_id,        topic.id        AS topic_id,        topic.title     AS topic_title,        topic.image_id  AS topic_image_id FROM topic          LEFT OUTER JOIN (     SELECT question.id AS id, question.text AS text, question.topic_id AS topic_id     FROM question     WHERE question.text ILIKE %(text_1)s ) AS anon_1 ON topic.id = anon_1.topic_id<\/code><\/pre>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 7<\/h4>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u044b \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043c\u0441\u044f \u0441 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u043e\u0439 \u0438 \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0439\u0434\u0435\u043c \u0442\u043e\u043f\u0438\u043a\u0438, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u043e\u043b\u044c\u0448\u0435 \u0434\u0435\u0441\u044f\u0442\u0438 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p>\u0412 \u0430\u043b\u0445\u0438\u043c\u0438\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0441\u0445\u043e\u0436\u0438\u0439 \u0441 Django \u043f\u043e\u0434\u0445\u043e\u0434: \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441, \u0430 \u043f\u043e\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0435\u0433\u043e \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0441\u0435\u043b\u0435\u043a\u0442\u0435:<\/p>\n<pre><code class=\"python\">topic_ids = s.query(     Question.topic_id.label('topic_id'), ).group_by(Question.topic_id).having(     sa.func.count(Question.id) > 1, )  topics = s.query(Topic).filter(Topic.id.in_(topic_ids))  for t in topics:     print(f'{t.title}')<\/code><\/pre>\n<p>\u0412 \u0431\u0430\u0437\u0443 \u0443\u0445\u043e\u0434\u0438\u0442 \u0442\u0430\u043a\u043e\u0439 \u0436\u0435 \u0437\u0430\u043f\u0440\u043e\u0441, \u043a\u0430\u043a \u0432 Django:<\/p>\n<pre><code class=\"sql\">SELECT topic.id AS topic_id, topic.title AS topic_title, topic.image_id AS topic_image_id  FROM topic  WHERE topic.id IN (   SELECT question.topic_id AS topic_id    FROM question GROUP BY question.topic_id    HAVING count(question.id) > %(count_1)s )<\/code><\/pre>\n<p>\u0411\u0443\u0434\u044c\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b: \u043f\u0440\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043b <code>.subquery()<\/code> \u043a \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e <code>topic_ids<\/code>, \u0430 \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u043b\u0438\u0448\u043d\u0435\u043c\u0443 \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441\u0443:<\/p>\n<pre><code class=\"sql\">SELECT topic.id AS topic_id, topic.title AS topic_title, topic.image_id AS topic_image_id FROM topic WHERE topic.id IN (     SELECT anon_1.topic_id     FROM (              SELECT question.topic_id AS topic_id              FROM question              GROUP BY question.topic_id              HAVING count(question.id) > %(count_1)s          ) AS anon_1 )<\/code><\/pre>\n<p>\u041d\u0435 \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e, \u043d\u043e \u0437\u0430\u0447\u0435\u043c \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0439 \u043a\u043e\u0434? \u0414\u0430 \u0438 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u043e\u0442 \u043f\u0440\u0438\u0434\u0438\u0440\u0447\u0438\u0432\u043e\u0433\u043e DBA \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 8<\/h4>\n<p>\u042d\u0442\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d \u043e\u0431\u0437\u043e\u0440\u0443 common table expression (CTE), \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0447\u0430\u0441\u0442\u0435\u043d\u044c\u043a\u043e \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0448\u044c\u0441\u044f \u043f\u0440\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0441\u044b\u0440\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a PostgreSQL \u0440\u0430\u0434\u0438 \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u0438 \u0438 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430.<\/p>\n<p>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u0438\u0437 \u0431\u0430\u0437\u044b \u0442\u043e\u043f\u0438\u043a\u0438, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u0431\u043e\u043b\u044c\u0448\u0435 \u0434\u0435\u0441\u044f\u0442\u0438. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c CTE, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043d\u0430\u0439\u0434\u0435\u043c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u043d\u0443\u0436\u043d\u044b\u0445 \u0442\u043e\u043f\u0438\u043a\u043e\u0432:<\/p>\n<pre><code class=\"python\">topic_ids = s.query(Question.topic_id.label('topic_id')).filter(     Question.text.ilike('%best%'), ).group_by(Question.topic_id).having(     sa.func.count(Question.id) > 10, ).cte(name='topic_ids')<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c CTE \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0442\u043e\u043f\u0438\u043a\u0438:<\/p>\n<pre><code class=\"python\">topics = s.query(Topic).filter(Topic.id.in_(sa.select([topic_ids.c.topic_id]))) print(', '.join(t.title for t in topics))<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0442\u0430\u043a\u043e\u0439:<\/p>\n<pre><code class=\"sql\">WITH topic_ids AS (   SELECT question.topic_id AS topic_id    FROM question    WHERE question.text ILIKE %(text_1)s   GROUP BY question.topic_id    HAVING count(question.id) > %(count_1)s ) SELECT topic.id AS topic_id, topic.title AS topic_title, topic.image_id AS topic_image_id  FROM topic  WHERE topic.id IN (   SELECT topic_ids.topic_id    FROM topic_ids )<\/code><\/pre>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 9<\/h4>\n<p>\u0417\u0434\u0435\u0441\u044c \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a many-to-many \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f\u043c. \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u043e\u043f\u0438\u043a\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u043c\u0435\u044e\u0442 \u043a \u043d\u0435\u043c\u0443 \u0434\u043e\u0441\u0442\u0443\u043f.<\/p>\n<p>\u0418 \u0441\u043d\u043e\u0432\u0430 \u043c\u043e\u0436\u043d\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0438\u043b\u0438\u0439 \u0441 \u043d\u0430\u0448\u0435\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0432\u0441\u0451 \u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u0430 \u043d\u0430\u0441. \u041e\u0434\u043d\u0430\u043a\u043e \u0437\u0430 \u0442\u0430\u043a\u0443\u044e \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0440\u0430\u0441\u043f\u043b\u0430\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f. \u0415\u0441\u043b\u0438 \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u043f\u0446\u0438\u0438, \u0442\u043e \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u043e\u043f\u0438\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0437\u0430 \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439:<\/p>\n<pre><code class=\"python\">for t in s.query(Topic).all():  # sa.9.1     names = ', '.join(u.name for u in t.users)   # sa.9.2     print(f'Topic[{t.title}]: {names}')<\/code><\/pre>\n<pre><code class=\"sql\">-- sa.9.1 SELECT topic.id AS topic_id, topic.title AS topic_title, topic.image_id AS topic_image_id FROM topic;  -- sa.9.2 SELECT \"user\".id AS user_id, \"user\".name AS user_name  FROM \"user\", topic_user  WHERE %(param_1)s = topic_user.topic_id AND \"user\".id = topic_user.user_id  -- sa.9.2 SELECT \"user\".id AS user_id, \"user\".name AS user_name  FROM \"user\", topic_user  WHERE %(param_1)s = topic_user.topic_id AND \"user\".id = topic_user.user_id <\/code><\/pre>\n<p>\u0422\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0442 \u0437\u0430\u043f\u0440\u043e\u0441, \u043f\u043e\u0440\u043e\u0436\u0434\u0430\u0435\u043c\u044b\u0439 <code>sa.9.2<\/code>, \u0431\u0443\u0434\u0435\u0442 \u0431\u0435\u0437 <code>INNER JOIN<\/code>. \u0422\u0430\u043c \u0434\u0435\u043a\u0430\u0440\u0442\u043e\u0432\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u0435\u043c \u0432\u044b\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u043d\u0443\u0436\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438, \u0438 \u0442\u0430\u043a \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f. \u041d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u0441\u043d\u043e\u0432\u0430 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u043e\u043f\u0446\u0438\u0438:<\/p>\n<pre><code class=\"python\">for t in s.query(Topic).options(         joinedload('users'), ).all():     names = ', '.join(u.name for u in t.users)     print(f'Topic[{t.title}]: {names}')<\/code><\/pre>\n<pre><code class=\"sql\">SELECT topic.id       AS topic_id,        topic.title    AS topic_title,        topic.image_id AS topic_image_id,        user_1.id      AS user_1_id,        user_1.name    AS user_1_name FROM topic          LEFT OUTER JOIN (topic_user AS topic_user_1 JOIN \"user\" AS user_1 ON user_1.id = topic_user_1.user_id)                          ON topic.id = topic_user_1.topic_id<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u043a \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f (\u0443 \u043d\u0430\u0441 \u044d\u0442\u043e \u043f\u043e\u043b\u0435 <code>TopicUser.role<\/code>), \u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u0438 \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e <a href=\"https:\/\/docs.sqlalchemy.org\/en\/13\/orm\/basic_relationships.html#association-object\">\u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0443 Association Object<\/a>. \u0412 \u043d\u0430\u0448\u0438\u0445 \u0441\u0445\u0435\u043c\u0430\u0445 \u0441\u043c\u043e\u0442\u0440\u0438 \u0437\u0430\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u043e\u0434 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u043c <code># association.<\/code> \u0422\u0430\u043c \u0436\u0435 \u0435\u0441\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440 \u00ab\u043e\u0431\u0440\u0430\u0442\u043d\u044b\u0445\u00bb \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439: \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043d\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0442\u043e\u043f\u0438\u043a\u0430, \u0430 \u043d\u0430\u0431\u043e\u0440 \u0442\u043e\u043f\u0438\u043a\u043e\u0432, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e.<\/p>\n<pre><code class=\"python\">with session_scope() as s:     u = s.query(User).filter(User.id == 1).first()  # sa.9.3     for t in u.topics:  # sa.9.4         print(f'{u.name} is {t.role} in topic \"{t.topic.title}\"')  # sa.9.5<\/code><\/pre>\n<pre><code class=\"sql\">-- sa.9.3 SELECT \"user\".id AS user_id, \"user\".name AS user_name  FROM \"user\"  WHERE \"user\".id = %(id_1)s  -- sa.9.4 SELECT topic_user.id AS topic_user_id, topic_user.topic_id AS topic_user_topic_id, topic_user.user_id AS topic_user_user_id, topic_user.role AS topic_user_role  FROM topic_user  WHERE %(param_1)s = topic_user.user_id  -- sa.9.5 SELECT topic.id AS topic_id, topic.title AS topic_title, topic.image_id AS topic_image_id  FROM topic  WHERE topic.id = %(param_1)s  -- sa.9.5 SELECT topic.id AS topic_id, topic.title AS topic_title, topic.image_id AS topic_image_id  FROM topic  WHERE topic.id = %(param_1)s<\/code><\/pre>\n<p>\u0418 \u0441\u043d\u043e\u0432\u0430 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0446\u0438\u043a\u043b \u043d\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043f\u0440\u043e\u0432\u043e\u0446\u0438\u0440\u0443\u0435\u0442 \u043b\u0438\u0448\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0431\u0430\u0437\u0435. \u0427\u0442\u043e\u0431\u044b \u0438\u0445 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u043a\u0430\u0436\u0435\u043c, \u0447\u0442\u043e \u043c\u044b \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0437\u043d\u0430\u0435\u043c, \u0447\u0442\u043e \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0442\u043e\u043f\u0438\u043a\u0430\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<pre><code class=\"python\">u = s.query(User).filter(User.id == 1).options(     joinedload('topics'),     selectinload('topics.topic'), ).first()  for t in u.topics:     print(f'{u.name} is {t.role} in topic \"{t.topic.title}\"') <\/code><\/pre>\n<pre><code class=\"sql\">SELECT anon_1.user_id        AS anon_1_user_id,        anon_1.user_name      AS anon_1_user_name,        topic_user_1.id       AS topic_user_1_id,        topic_user_1.topic_id AS topic_user_1_topic_id,        topic_user_1.user_id  AS topic_user_1_user_id,        topic_user_1.role     AS topic_user_1_role FROM (          SELECT \"user\".id AS user_id, \"user\".name AS user_name          FROM \"user\"          WHERE \"user\".id = %(id_1)s          LIMIT %(param_1)s      ) AS anon_1          LEFT OUTER JOIN topic_user AS topic_user_1 ON anon_1.user_id = topic_user_1.user_id  SELECT topic.id AS topic_id, topic.title AS topic_title, topic.image_id AS topic_image_id  FROM topic  WHERE topic.id IN (%(primary_keys_1)s, %(primary_keys_2)s)<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0437\u0434\u0435\u0441\u044c \u0432\u044b\u0442\u044f\u0433\u0438\u0432\u0430\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c\u0438 \u0435\u043c\u0443 \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438 <code>topic_user<\/code>, \u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u0438\u0449\u0435\u0442 \u043d\u0443\u0436\u043d\u044b\u0435 \u0442\u043e\u043f\u0438\u043a\u0438. \u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0436\u0435 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0441\u043a\u0440\u044b\u0442\u044b\u043c \u043e\u0442 \u043d\u0430\u0441 \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0432 \u043a\u043e\u0434\u0435 \u0430\u043b\u0445\u0438\u043c\u0438\u0438.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 10<\/h4>\n<p>\u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438. \u041f\u0440\u0438 \u0432\u0441\u0442\u0430\u0432\u043a\u0435 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043d\u043e\u0432\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0434\u043b\u044f \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f bulk-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u0438. \u041e\u043d\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0437\u0430 \u043e\u0434\u0438\u043d \u0437\u0430\u043f\u0440\u043e\u0441 \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u0441\u0442\u0440\u043e\u043a.<\/p>\n<pre><code class=\"python\">s.bulk_save_objects([     Topic(title=f'topic {i}', image_id=1)     for i in range(3) ])<\/code><\/pre>\n<p>\u0412 \u0430\u043b\u0445\u0438\u043c\u0438\u0438 Python-\u043a\u043e\u0434 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 Django. \u041d\u043e \u0432\u043e\u0442 SQL \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0435\u043e\u0431\u044b\u0447\u043d\u043e:<\/p>\n<pre><code class=\"sql\">INSERT INTO topic (title, image_id) VALUES (%(title)s, %(image_id)s) ({'title': 'topic 0', 'image_id': 1}, {'title': 'topic 1', 'image_id': 1}, {'title': 'topic 2', 'image_id': 1})<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0435 \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0432\u0441\u0442\u0430\u0432\u043a\u0443. \u0422\u0430\u043a \u0436\u0435 \u0438 \u0441 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435\u043c, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043d\u0438\u0436\u0435.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 11.<\/h4>\n<p>\u0414\u0440\u0443\u0433\u0430\u044f \u0441\u0442\u043e\u0440\u043e\u043d\u0430 bulk-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u2014 \u044d\u0442\u043e \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435. \u0412 \u0430\u043b\u0445\u0438\u043c\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c\u0441\u044f \u0441\u043b\u043e\u0432\u0430\u0440\u044f\u043c\u0438 \u0441 PK \u0438 \u043f\u043e\u043b\u044f\u043c\u0438 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"python\">s.bulk_update_mappings(     User,     [dict(id=1, name='new 1 name'), dict(id=2, name='new 2 name')] )<\/code><\/pre>\n<pre><code class=\"sql\">UPDATE \"user\" SET name=%(name)s WHERE \"user\".id = %(user_id)s ({'name': 'new 1 name', 'user_id': 1}, {'name': 'new 2 name', 'user_id': 2})<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u0432 \u043b\u043e\u0433\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u0434\u0440\u0443\u0433\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441, \u0438 \u043e\u043d \u043d\u0435 \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435. \u042f \u043d\u0435 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043b \u044d\u0442\u043e\u0442 \u0432\u043e\u043f\u0440\u043e\u0441 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e, \u043d\u043e \u0432 <a href=\"https:\/\/docs.sqlalchemy.org\/en\/14\/orm\/session_api.html#sqlalchemy.orm.Session.bulk_update_mappings\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a> \u0441\u043a\u0430\u0437\u0430\u043d\u043e, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f executemany. \u0415\u0441\u043b\u0438 \u0440\u0435\u0447\u044c \u043e\u0431 <a href=\"https:\/\/www.psycopg.org\/docs\/cursor.html#cursor.executemany\">\u044d\u0442\u043e\u043c<\/a>, \u0442\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0432\u044b\u0438\u0433\u0440\u044b\u0448\u0430 \u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043c\u044b \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043c. \u041d\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u044e\u0441\u044c, \u044d\u0442\u043e \u0434\u043e\u0433\u0430\u0434\u043a\u0438. \u041e\u0441\u0442\u0430\u0432\u0438\u043c \u044d\u0442\u043e \u0441\u0432\u0435\u0434\u0443\u0449\u0435\u043c\u0443 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0442\u043e\u0440\u0443 \u0438\u043b\u0438 \u0434\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0410\u043b\u0445\u0438\u043c\u0438\u044f \u043c\u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u043c \u0432 \u043e\u0441\u0432\u043e\u0435\u043d\u0438\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c, \u0447\u0435\u043c Django ORM, \u043d\u043e \u0438 \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u0438\u043c. \u0422\u0430\u043a\u0436\u0435 \u0430\u043b\u0445\u0438\u043c\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0432 \u043b\u044e\u0431\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a ORM \u043e\u0442 Django \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432 \u043e\u0442\u0440\u044b\u0432\u0435 \u043e\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430. \u041e\u0447\u0435\u043d\u044c \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043f\u043e\u0449\u0443\u043f\u0430\u0442\u044c \u0430\u043b\u0445\u0438\u043c\u0438\u044e 2.0 \u0441 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0449\u0438\u043d\u044b, \u043d\u043e \u043f\u043e\u043a\u0430 \u043d\u0435 \u0434\u043e\u0448\u043b\u0438 \u0440\u0443\u043a\u0438.<\/p>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0432\u044b \u0443\u0437\u043d\u0430\u043b\u0438 \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0435 \u0438\u0437 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438. \u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437 \u043e\u043a\u0443\u043d\u0435\u043c\u0441\u044f \u0432 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 go-pg, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043d\u0430 Go, \u0433\u0434\u0435 \u0435\u0441\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 PostgreSQL. \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0438 \u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0439\u0442\u0435, \u0447\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043a\u043e\u0432\u0430\u0440\u043d\u044b, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0439\u0442\u0435, \u0447\u0442\u043e \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0437\u0430 \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u0432 \u043f\u0430\u0440\u0443 \u0441\u0442\u0440\u043e\u043a.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/581304\/\"> https:\/\/habr.com\/ru\/articles\/581304\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0410\u043b\u0435\u043a\u0441\u0435\u0439 \u041a\u0430\u0437\u0430\u043a\u043e\u0432, \u044f \u0442\u0435\u0445\u043b\u0438\u0434 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0435 \u043a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u0438\u00bb \u0432 \u0414\u043e\u043c\u043a\u043b\u0438\u043a. \u041f\u043e \u043c\u043e\u0435\u043c\u0443 \u043e\u043f\u044b\u0442\u0443 \u043f\u043e\u0434\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0435 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e Object Relational Mapper. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0443 \u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c \u0432\u0430\u0441 \u0441 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u043c\u0438 ORM, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u043b\u0438\u0441\u044c \u043c\u043d\u0435 \u0432 \u043f\u0440\u043e\u0434\u043e\u0432\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445. \u0412 <a href=\"https:\/\/habr.com\/ru\/company\/domclick\/blog\/552930\/\">\u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437<\/a> \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u043b\u0438 Django ORM , \u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043d\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0432\u0441\u0435\u043c\u043e\u0433\u0443\u0449\u0438\u0439 <a href=\"https:\/\/www.sqlalchemy.org\/\">SQLAlchemy<\/a>.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0411\u0443\u0434\u0435\u043c \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u043d\u0430:<\/p>\n<ul>\n<li>\n<p>\u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0441\u0445\u0435\u043c\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 (\u0441\u044b\u0440\u043e\u0439 SQL);<\/p>\n<\/li>\n<li>\n<p>\u043e\u043f\u0438\u0448\u0435\u043c \u044d\u0442\u0443 \u0441\u0445\u0435\u043c\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e alchemy-\u043c\u043e\u0434\u0435\u043b\u0435\u0439;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043c\u0441\u044f \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0445\u0438\u0442\u0440\u043e\u0441\u0442\u044f\u043c\u0438 \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u043e\u0442\u043b\u0430\u0434\u043a\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0430 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0438\u0437\u0443\u0447\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0441\u043e\u0431\u043e\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0443\u0434\u0435\u043b\u0438\u043c \u0441\u044b\u0440\u043e\u043c\u0443 SQL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430. \u0412\u0435\u0434\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u043e\u0442 \u043d\u0435\u0433\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<h2>\u0421\u0445\u0435\u043c\u0430<\/h2>\n<p>\u0421\u0445\u0435\u043c\u0443 \u043c\u044b \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u043d\u043e\u0439 \u043d\u0430 \u043f\u0440\u043e\u0442\u044f\u0436\u0435\u043d\u0438\u0438 \u0432\u0441\u0435\u0445 \u0441\u0442\u0430\u0442\u0435\u0439. \u041f\u0443\u0441\u0442\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 (User) \u043c\u043e\u0433\u0443\u0442 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u043e\u043f\u0440\u043e\u0441\u044b (Question) \u0432\u043d\u0443\u0442\u0440\u0438 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0435\u043c (Topic). \u0423 \u0442\u043e\u043f\u0438\u043a\u0430 \u0435\u0441\u0442\u044c \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430 (Image). \u0414\u043e\u0441\u0442\u0443\u043f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043a \u0442\u043e\u043f\u0438\u043a\u0443 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 many-to-many \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 TopicUser, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043a\u0440\u043e\u043c\u0435 ForeignKey (FK) \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 FK \u0434\u043b\u044f \u0442\u043e\u043f\u0438\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u2014 \u0440\u043e\u043b\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u0442\u043e\u043f\u0438\u043a\u0435.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0438\u043c SQL-\u0435\u043c:<\/p>\n<pre><code class=\"sql\">CREATE TABLE \"image\" (     \"id\"   serial NOT NULL PRIMARY KEY,     \"name\" text   NOT NULL );  CREATE TABLE \"topic\" (     \"id\"       serial  NOT NULL PRIMARY KEY,     \"title\"    text    NOT NULL,     \"image_id\" integer REFERENCES \"image\" (\"id\") NOT NULL );  CREATE TABLE \"user\" (     \"id\"   serial NOT NULL PRIMARY KEY,     \"name\" text   NOT NULL );  CREATE TABLE \"topic_user\" (     \"id\"       serial  NOT NULL PRIMARY KEY,     \"role\"     text    NOT NULL,     \"topic_id\" integer REFERENCES \"topic\" (\"id\") NOT NULL,     \"user_id\"  integer REFERENCES \"user\" (\"id\") NOT NULL );  CREATE TABLE \"question\" (     \"id\"       serial  NOT NULL PRIMARY KEY,     \"text\"     text    NOT NULL,     \"topic_id\" integer REFERENCES \"topic\" (\"id\") NOT NULL  );<\/code><\/pre>\n<h2>Alchemy models<\/h2>\n<p>\u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c SQL-\u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0432 \u043d\u0430\u0448\u0435\u043c Python-\u043a\u043e\u0434\u0435, \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439. \u041e\u0431\u044b\u0447\u043d\u043e \u0435\u0433\u043e \u043d\u0430\u0437\u044b\u0432\u0430\u044e\u0442 <code>Base<\/code>, \u0438 \u0432\u0441\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u044e\u0442 \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430. \u042d\u0442\u043e\u0442 declarative base class \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a \u0432\u0441\u0435\u0445 \u00ab\u0441\u0432\u043e\u0438\u0445\u00bb \u0442\u0430\u0431\u043b\u0438\u0446 \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0435\u043c\u0443 \u043a\u043b\u0430\u0441\u0441\u043e\u0432. \u041e\u0431\u044b\u0447\u043d\u043e <code>Base<\/code> \u043e\u0434\u0438\u043d \u043d\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0435\u0433\u043e \u0437\u0430\u0432\u043e\u0434\u044f\u0442 \u0432 \u043e\u0431\u0449\u0435\u043c \u043c\u043e\u0434\u0443\u043b\u0435. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0440\u0430\u0437\u043d\u044b\u0445 \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0440\u0430\u0437\u043d\u044b\u043c \u0431\u0430\u0437\u0430\u043c \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">from sqlalchemy.ext.declarative import declarative_base  Base = declarative_base()   class Image(Base):     __tablename__ = 'image'      id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)     name = sa.Column(sa.Text, nullable=False)   class Topic(Base):     __tablename__ = 'topic'      id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)     title = sa.Column(sa.Text, nullable=False)     image_id = sa.Column(sa.Integer, sa.ForeignKey('image.id'), nullable=False)     image = sa.orm.relationship(Image)  # innerjoin=True \u0434\u043b\u044f JOIN     questions = sa.orm.relationship('Question')      users = sa.orm.relationship('User', secondary='topic_user')     # association     # users = sa.orm.relationship('TopicUser', back_populates='topic')   class User(Base):     __tablename__ = 'user'      id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)     name = sa.Column(sa.Text, nullable=False)      # association     # topics = sa.orm.relationship('TopicUser', back_populates='user')   class TopicUser(Base):     __tablename__ = 'topic_user'      id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)     topic_id = sa.Column(sa.Integer, sa.ForeignKey('topic.id'))     user_id = sa.Column(sa.Integer, sa.ForeignKey('user.id'))     role = sa.Column(sa.Text)      # association     # user = sa.orm.relationship(User, back_populates='topics')     # topic = sa.orm.relationship(Topic, back_populates='users')   class Question(Base):     __tablename__ = 'question'      id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)     text = sa.Column(sa.Text)     topic_id = sa.Column(sa.Integer, sa.ForeignKey('topic.id'), nullable=False)     topic = sa.orm.relationship(Topic)  # innerjoin=True \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f JOIN \u0432\u043c\u0435\u0441\u0442\u043e LEFT JOIN <\/code><\/pre>\n<\/div>\n<\/details>\n<h2>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430<\/h2>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0431\u0430\u0437\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0432\u0438\u0436\u043a\u0430, \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f. \u0422\u0430\u043a\u0436\u0435 \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>echo=True<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u0432\u0438\u0434\u0435\u0442\u044c \u0432\u0441\u0435 \u0442\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0430\u043b\u0445\u0438\u043c\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437 \u043d\u0430\u0448\u0435\u0433\u043e Python-\u043a\u043e\u0434\u0430 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0432 \u0411\u0414.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0441\u0435\u0441\u0441\u0438\u0439. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u043c\u0443 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0443 \u0432\u0441\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0435 \u0432 \u043d\u0435\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u0435\u0441\u0441\u0438\u044f \u0431\u0443\u0434\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u043a\u043e\u043c\u043c\u0438\u0442\u0438\u0442\u044c, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0431\u044b\u043b\u043e \u043e\u0448\u0438\u0431\u043e\u043a \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u043a\u0430\u0442\u044b\u0432\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e \u0441\u0435\u0441\u0441\u0438\u0438 \u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438 \u043f\u043e \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c <a href=\"https:\/\/docs.sqlalchemy.org\/en\/14\/orm\/session_basics.html#session-faq-whentocreate\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">from contextlib import contextmanager  import sqlalchemy as sa from sqlalchemy.orm import sessionmaker  main_engine = sa.create_engine(     'postgres:\/\/localhost:5432\/habr_sql?sslmode=disable',     echo=True, )  DBSession = sessionmaker(     binds={         Base: main_engine,     },     expire_on_commit=False, )   @contextmanager def session_scope():     \"\"\"Provides a transactional scope around a series of operations.\"\"\"     session = DBSession()     try:         yield session         session.commit()     except Exception as e:         session.rollback()         raise e     finally:         session.close()  if __name__ == '__main__':     with session_scope() as s:         &lt;actual_code><\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0445 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043e\u0432 \u043a\u043e\u0434\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0432\u0441\u0435\u0445 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432. \u041d\u0430\u043f\u043e\u043c\u043d\u044e, \u0447\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0432 \u0441\u0442\u0430\u0442\u044c\u044f\u0445 \u0441\u043a\u0432\u043e\u0437\u043d\u044b\u0435, \u0442\u043e \u0435\u0441\u0442\u044c \u00ab\u041f\u0440\u0438\u043c\u0435\u0440 n\u00bb \u0432 \u043b\u044e\u0431\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e \u043e\u0434\u043d\u043e \u0438 \u0442\u043e \u0436\u0435.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 1<\/h4>\n<p>\u0425\u043e\u0442\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u0435\u0441\u044f\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u0438\u0437 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u043e\u043f\u0438\u043a\u0430.<\/p>\n<pre><code class=\"sql\">SELECT * FROM question WHERE topic_id = 1 ORDER BY id DESC LIMIT 10;<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u0430\u043b\u0445\u0438\u043c\u0438\u0438:<\/p>\n<pre><code class=\"python\">questions = s.query(Question).filter(     Question.topic_id == t1_id, ).order_by(Question.id.desc()).limit(10).all()<\/code><\/pre>\n<p>\u0421\u0440\u0430\u0437\u0443 \u0443\u0447\u0438\u043c\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c\u0443 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0443 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a \u043f\u043e\u043b\u044f\u043c \u043a\u043b\u0430\u0441\u0441\u0430. \u0412 Django \u0438\u043d\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434: \u0432 <code>filter<\/code> \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u043f\u043e \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043d\u043e\u043c\u0443 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0443, \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u043c\u0443 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u0432 \u0431\u0430\u0437\u0435. \u0417\u0434\u0435\u0441\u044c \u0436\u0435 \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 <code>Question.topic_id == t1_id<\/code> \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u0435\u0440\u0435\u0434\u0430\u0441\u0442\u0441\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 <code>BinaryExpression<\/code>.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 2<\/h4>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043d\u0430\u0439\u0442\u0438 \u0442\u0430\u043a\u0438\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0442\u043e\u043f\u0438\u043a\u0430, \u0432 \u0442\u0435\u043a\u0441\u0442\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043b\u0438\u0431\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u043f\u043e\u0434\u0441\u0442\u0440\u043e\u043a\u0430 <code>fart<\/code>, \u043b\u0438\u0431\u043e \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u044f <code>dog<\/code>, \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0438\u0445 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430. \u041c\u044b \u043b\u0435\u0433\u043a\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0437\u0438\u043c \u044d\u0442\u043e \u043d\u0430 SQL:<\/p>\n<pre><code class=\"sql\">SELECT * FROM question WHERE (   topic_id = 1 AND (       text ILIKE '%fart%' OR       NOT (text ILIKE '%dog%')   ) );<\/code><\/pre>\n<p>\u0412 \u0430\u043b\u0445\u0438\u043c\u0438\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 Django-\u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u044f \u0432\u0438\u0436\u0443 \u043b\u0438\u0448\u044c \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u00ab\u0438\u043b\u0438\u00bb:<\/p>\n<pre><code class=\"python\">questions = s.query(Question).filter(     Question.topic_id == 1,     sa.or_(Question.text.ilike('%fart%'), ~Question.text.ilike('%dog%')) )  for q in questions:     print(q.id)<\/code><\/pre>\n<p>\u0412 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0443\u0432\u0438\u0434\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 SQL-\u0437\u0430\u043f\u0440\u043e\u0441:<\/p>\n<pre><code class=\"sql\">SELECT question.id AS question_id, question.text AS question_text, question.topic_id AS question_topic_id  FROM question  WHERE question.topic_id = %(topic_id_1)s AND (   question.text ILIKE %(text_1)s OR question.text NOT ILIKE %(text_2)s )<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0437\u0430\u043f\u0440\u043e\u0441 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0441\u044f \u0432 \u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043d\u0430\u0447\u043d\u0435\u043c \u0438\u0442\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e <code>questions<\/code>. \u0414\u043e \u044d\u0442\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u0431\u0430\u0437\u0443 \u043d\u0435 \u0443\u0445\u043e\u0434\u0438\u043b\u043e, \u0430 \u0432 <code>questions<\/code> \u043b\u0435\u0436\u0430\u043b \u043e\u0431\u044a\u0435\u043a\u0442 <code>Query<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0435\u0449\u0451 \u043a\u0430\u043a-\u0442\u043e \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0434\u043e\u0431\u0430\u0432\u0438\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043b\u0438\u043c\u0438\u0442. \u041f\u043e\u0445\u043e\u0436\u0435\u0435 \u043c\u044b \u0432\u0438\u0434\u0435\u043b\u0438 \u0438 \u0432 Django. \u042d\u0442\u043e \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043b\u0435\u043d\u0438\u0432\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 (lazy loading).<\/p>\n<p>\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 Python-\u043a\u043e\u0434\u0430:<\/p>\n<pre><code class=\"python\">questions = s.query(Question).filter(   (Question.topic_id == 1) &amp;   (Question.text.ilike('%fart%') | ~Question.text.ilike('%dog%')) )<\/code><\/pre>\n<p>&#8230;\u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 3<\/h4>\n<p>\u042d\u0442\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u0434\u0432\u043e\u0434\u0438\u0442 \u043d\u0430\u0441 \u043a \u0442\u0435\u043c\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0430\u043c\u043e\u0433\u043e \u0432\u043e\u043f\u0440\u043e\u0441\u0430, \u043d\u043e \u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0441 \u043d\u0438\u043c \u0442\u043e\u043f\u0438\u043a\u0430. \u0412 \u0430\u043b\u0445\u0438\u043c\u0438\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u0445\u043e\u0436\u0438\u0439 \u043f\u0440\u0438\u043d\u0446\u0438\u043f. \u0420\u0430\u0431\u043e\u0442\u0430 \u00ab\u0432 \u043b\u043e\u0431\u00bb:<\/p>\n<pre><code class=\"python\">q = s.query(Question).filter(Question.id == 1).first()  # sa.3.1 print(q.topic.title)  # sa.3.2<\/code><\/pre>\n<p>&#8230;\u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u0442\u043e\u043c\u0443 \u0447\u0442\u043e, <code>sa.3.1<\/code> \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0437\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c, \u0430 <code>sa.3.2<\/code> \u2014 \u0437\u0430 \u0442\u043e\u043f\u0438\u043a\u043e\u043c. \u0427\u0442\u043e\u0431\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432 \u0431\u0430\u0437\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0437\u0430\u043f\u0440\u043e\u0441, \u043d\u0443\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u043f\u0446\u0438\u044f\u043c\u0438:<\/p>\n<pre><code class=\"python\">q = s.query(Question).filter(     Question.id == 1, ).options(joinedload(Question.topic)).first() print(q.topic.title)<\/code><\/pre>\n<p>\u0412 \u0430\u043b\u0445\u0438\u043c\u0438\u0438 \u044d\u0442\u043e\u0442 \u043f\u043e\u0434\u0445\u043e\u0434 \u043d\u043e\u0441\u0438\u0442 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 Eager Loading, \u0432\u043e\u0442 <a href=\"https:\/\/docs.sqlalchemy.org\/en\/13\/orm\/tutorial.html#eager-loading\">\u0441\u0441\u044b\u043b\u043a\u0430<\/a> \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u044b. \u041e\u043f\u0446\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043d\u043e \u0438 \u043f\u0440\u0438 <a href=\"https:\/\/docs.sqlalchemy.org\/en\/13\/orm\/loading_relationships.html\">\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043c\u043e\u0434\u0435\u043b\u0438<\/a>. \u041d\u043e \u043c\u043d\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u043f\u0446\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u0440\u0438 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 SQL \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0430\u0448\u0438\u043c \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f\u043c. \u0421\u043e\u0432\u0435\u0442\u0443\u044e \u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a \u043f\u0440\u0438 \u043b\u044e\u0431\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0435 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0412\u0440\u0435\u043c\u0435\u043d\u0438 \u044d\u0442\u043e \u0437\u0430\u0439\u043c\u0451\u0442 \u043f\u0430\u0440\u0443 \u043c\u0438\u043d\u0443\u0442, \u0437\u0430\u0442\u043e \u043f\u0440\u0438\u0434\u0430\u0441\u0442 \u0432\u0430\u043c \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0438 \u0441\u043f\u0430\u0441\u0451\u0442 \u043e\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e.<\/p>\n<pre><code class=\"sql\">SELECT question.id       AS question_id,        question.text     AS quetion_text,        question.topic_id AS question_topic_id,        topic_1.id        AS topic_1_id,        topic_1.title     AS topic_1_title,        topic_1.image_id  AS topic_1_image_id FROM question          LEFT OUTER JOIN topic AS topic_1 ON topic_1.id = question.topic_id WHERE question.id = %(id_1)s LIMIT %(param_1)s;<\/code><\/pre>\n<p>\u0412\u0441\u0451 \u043d\u0435\u043f\u043b\u043e\u0445\u043e, \u0432\u0435\u0434\u044c \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0442\u043e\u043f\u0438\u043a\u0430 \u0438 \u043d\u0435 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0445\u043e\u0434\u0438\u0442\u044c \u0432 \u0431\u0430\u0437\u0443. \u041d\u043e <code>LEFT JOIN<\/code> \u0432 \u043d\u0430\u0448\u0435\u0439 \u0441\u0445\u0435\u043c\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437\u043b\u0438\u0448\u0435\u043d, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u043e\u043f\u0440\u043e\u0441\u0430, \u043d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u043a \u0442\u043e\u043f\u0438\u043a\u0443. \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u043b\u0445\u0438\u043c\u0438\u0438 \u043f\u0440\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0438 relation-\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e <code>INNER JOIN<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u0435\u043d, \u0447\u0435\u043c <code>OUTER<\/code>:<\/p>\n<pre><code class=\"python\">topic = sa.orm.relationship(Topic, innerjoin=True)<\/code><\/pre>\n<p>\u0421 \u0442\u0430\u043a\u0438\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0447\u0435\u0441\u0442\u043d\u044b\u0439 <code>INNER JOIN<\/code>.<\/p>\n<p>\u0415\u0441\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u043d\u0430 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0430\u043b\u0445\u0438\u043c\u0438\u0438. \u041a\u0430\u043a \u044f \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u00ab\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430\u00bb, \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0441\u0435\u0441\u0441\u0438\u0438. \u041d\u043e \u0435\u0441\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043d\u0435\u0441\u0435\u043d \u0437\u0430 \u0441\u0435\u0441\u0441\u0438\u044e, \u0442\u043e \u0434\u043b\u044f \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043c\u044b \u043f\u043e\u0442\u0435\u0440\u044f\u0435\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u00ab\u043f\u043e\u0434\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0430 \u043b\u0435\u0442\u0443\u00bb. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"python\">with session_scope() as s:     q = s.query(Question).filter(Question.id ==<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-381921","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/381921","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=381921"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/381921\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=381921"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=381921"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=381921"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}