SQLAlchemy study notes (b): ORM base

As usual look at the hierarchical graph

First, the claim mapping relationship

When using the ORM, we first need to define the table to be operated (by  Table), and then define the table corresponding Python class, and a mapping relationship between the two statements (through  Mapper).

Convenience, SQLAlchemy provides Declarative system to complete the three steps above once, Declarative system provides base class, the base class will inherit its Python class (may be referred to as model) to create a Table, and maintain the mapping relationship between the two.

from sqlalchemy.ext.declarative import declarative_base
from SQLAlchemy import Column, Integer, String

Base = declarative_base()  # 拿到 Base 类


class User(Base):
    id = Column(Integer, primary_key=True)
    username = Column(String(32), nullable=False, index=True)  # 添加 index 提升搜索效率
    fullname = Column(String(64))
    password = Column(String(32))  # 真实情况下一般只存 hash

    def __repr__(self):
        return f"<User {self.username}>"

This specifies a good object - relational mapping, the article said that all the Table in a MetaData in, you can  Base.metadata get it.

Base.metadata.create_all(engine)  # 通过 metadata 创建表(或者说生成模式 schema)

See engine to create articles on the document  SQLAlchemy Study Notes (a): Engine and SQL expression language

Restrictions

Refer to  SQL base notes (three): Constraints  and  SQLAlchemy study notes (a): Engine and SQL expression language - table constraint definition

Using ORM to define constraints, and direct use of SQL expression language definition is very similar, there are two ways:

  1. Directly as a constraint  Column, ForeignKey the argument. In this way the most simple and most commonly used.
  2. Use  UniqueConstraint, CheckConstraint other types of configuration constraints, then placed  __table_args__ properties. For example:
class User(Base):
    id = Column(Integer, primary_key=True)
    username = Column(String(32), nullable=False, index=True)  # 添加 index 提升搜索效率
    fullname = Column(String(64))
    password = Column(String(32))  # 真实情况下一般只存 hash

    # 顾名思义,这是 `Table` 类的参数的序列。里面的约束条件会被用于构建 __table__
    __table_args__ = (UniqueConstraint('username', name='c_user'),)  # username 的唯一性约束

    def __repr__(self):
        return f"<User {self.username}>"

Second, the acquisition session

When speaking on an engine, we are here to interact with the database through the connection, and in the ORM we use Session to access the database.

from sqlalchemy.orm import sessionmaker

Session = sessionmaker(bind=engine)  # 获取 session

Third, the CRUD

When direct SQL expression language, we use the insert (), select (), update (), delete () function construct four SQL, using the where () to add conditions using model.join (another_model) perform join operations.
While using ORM, database operations no longer correspond directly with SQL. We are now operated by the operation of the Python object database.

Now, through db.session.add (), db.session.delete () add and delete, use db.session.query (Model) query, add filters through the filter and filter_by.
The changes are to check out the corresponding row object directly modify the object, and then commit on the line.

  1. Add:
ed_user = User(name='ed', fullname='Ed Jones', password='edspassword')  # 用构造器构造对象
session.add(ed_user)  # 添加,此外还有批量添加 add_all([user1, user2...])
session.commit()  # 必须手动 commit
  1. modify:
ed_user = session.query(User).filter_by(name='ed').first()  # 先获取到 User 对象
ed_user.password = 'f8s7ccs'  # 改了密码
session.commit()  # 提交

# 批量修改
session.query(User).filter(User.home=='shanghai') \
    .update({User.login_num:0})  # 将所有上海的用户的 login_num 设为 0
session.commit()
  1. delete:
ed_user = session.query(User).filter_by(name='ed').first()  # 先获取到 User 对象
session.delete(ed_user)  # 直接删除(session 知道 ed_user 属于哪个表)
session.commit()  # 提交

# 批量删除
session.query(User).filter(User.home=='shanghai') \
    .delete()  # 删除所有上海的用户

session.commit()

Similarly, you can also check for abnormalities on the outside, and then call the  session.rollback() realization failed rollback.

IV Advanced Search

  1. filter_by: using keywords to filter parameters, the previous demonstration has been used many times.
  2. filter: it corresponds to the SQL expression language where, supports a variety of complex SQL syntax.
  3. group_by: grouping by specifying column
  4. distinct (): de-duplication
  5. join (): association
query.filter(User.name == 'ed')  # 这个等同于 filter_by,但是更繁琐
query.filter(User.name != 'ed')  # 不等于,这个就是 filter_by 无法做到的了
query.filter(User.name.like('%ed%'))  # SQL like 的 like 语法
query.filter(User.name.in_(['ed', 'wendy', 'jack']))  # 包含

# 查询还可以嵌套
query.filter(User.name.in_(
    session.query(User.name).filter(User.name.like('%ed%'))
))

query.filter(~User.name.in_(['ed', 'wendy', 'jack']))  # 不包含
query.filter(User.name == None)  # NULL 对应 Python 的 None

from sqlalchemy import or_, and_, in_
query.filter(or_(User.name == 'ed', User.name == 'wendy'))  # OR 语法

query.group_by(User.name)  # 分组
query.distinct()  # 去重

from sqlalchemy import func  # SQL 函数包
session.query(func.count(User.name)).filter_by(xxx=xxx)  # 使用 count 函数

# join 关联
# 默认使用内联(inner),即只取两表的交集
session.query(User, Address).filter(User.id==Address.user_id)  # 方法一

session.query(User).join(Address).\  # 方法二
    filter(Address.email_address=='[email protected]')

# 外联 outer join,将另一表的列联结到主表,没有的行为 NULL
session.query(User).outerjoin(User.addresses) \
    .filter(Address.email_address=='[email protected]')

Execute a query to retrieve data

The query returns the query object, but SQL has not been executed until you call the following several methods:

# 构造 query 对象
query = session.query(User).filter(User.name.like('%ed')).order_by(User.id)

# 1. all 返回所有结果的列表
res_list = query.all()

# 2. first 先在 SQL 中加入限制 `limit 1`,然后执行。
res = query.first()

# 3. one 执行 sql 并获取所有结果
# 如果结果不止一行,抛出 MultipleResultsFound Error!!!
# 如果结果为空,抛出 NoResultFound Error !!!
res = query.one()

4. one_or_none 差别在于结果为空,它不抛出异常,而是返回 None
res = query.one_or_none()

reference

Published 131 original articles · won praise 7 · views 30000 +

Guess you like

Origin blog.csdn.net/weixin_43064185/article/details/103664330
Recommended