Official website document
https://flask-sqlalchemy.palletsprojects.com/en/master/quickstart/
Database settings
The relational model database is widely used in Web applications. The relational database stores all data in the table. The table is used to model the entity of the application. The number of columns in the table is fixed and the number of rows is variable. It uses a structured query language. The columns of a relational database define the data attributes of the entities represented in the table. For example, there are name, price, number, etc. in the product list. Flash itself does not limit the choice of database. You can choose either SQL or NOSQL. You can also choose a more convenient SQLALchemy, similar to Django's ORM. SQLALchemy is actually the database www.meimeimeitu8 Com abstraction allows developers to operate the database through Python objects instead of directly dealing with SQL statements. While discarding some performance overhead, it is in exchange for a great improvement in development efficiency.
SQLAlchemy is a relational database framework, which provides the operation of high-level ORM and low-level native database. Flash SQLAlchemy is a flash extension that simplifies SQL alchemy operations.
The following uses mysql as an example.
Create mysql database
1. Log in to the database
mysql -u root -p password
2. Create a database and set the code
create database <Database name> charset=utf8;
3. Display all databases
show databases;
4. The implementation is as follows:
mysql> create database flask_ex charset=utf8; Query OK, 1 row affected (0.06 sec)
Install the extension of flash Sqlalchemy
pip install -U Flask-SQLAlchemy
python2: to connect to mysql database, you still need to install flash mysql dB
pip install flask-mysqldb
Python 3: to connect to mysql database www.rsxedu.com COM, you still need to install pymysql
pip install pymysql
This chapter begins with Python 3.
Use flask Sqlalchemy to connect to mysql database
To use Flask Sqlalchemy to expand the operation database, you first need to establish a database connection. The database connection is specified by URL, and the database used by the program must be saved to Sqlalchemy of the flash configuration object_ DATABASE_ Uri key.
Compare the database settings in Django and Flask:
Django's database settings:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # Modify the backend database and use mysql 'NAME': 'mydb', # Set access database name 'USER': 'root', # Access mysql user name 'PASSWORD': 'password', # Set access password 'HOST': 'localhost', # Set access ip address 'PORT': 3306, # Set access port number } }
Database settings for flash:
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/flask_ex'
Common SQLAlchemy field types
After reading how to set up the connection database, let's take a look. When using SQLAlchemy to create a data model, the basic field types are as follows:
Type name | Types in python | explain |
---|---|---|
Integer | int | Ordinary integer, usually 32 bits |
SmallInteger | int | An integer with a small value range, usually 16 bits |
BigInteger | int or long | Integer with unlimited precision |
Float | float | Floating point number |
Numeric | decimal.Decimal | Ordinary integer, usually 32 bits |
String | str | Variable length string |
Text | str | Variable length string, which is optimized for long or unlimited length strings |
Unicode | unicode | Variable length Unicode string |
UnicodeText | unicode | Variable length Unicode string, optimized for long or unlimited length strings |
Boolean | bool | Boolean value |
Date | datetime.date | time |
Time | datetime.datetime | Date and time |
LargeBinary | str | Binary file |
Common SQLAlchemy column options
Option name | explain |
---|---|
primary_key | If True, it represents the primary key of the table |
unique | If True, it means that duplicate values are not allowed in this column |
index | If True, create an index for this column to improve query efficiency |
nullable | If True, null values are allowed; if False, null values are not allowed |
default | Define default values for this column |
Common SQLAlchemy relationship options
Option name | explain |
---|---|
backref | Add reverse references to the first mock exam in another model of the relationship. |
primary join | Explicitly specify the join conditions used between the two models |
uselist | If False, scalar values are used instead of lists |
order_by | Specifies how records in the relationship are sorted |
secondary | Specifies how records in many to many are sorted |
secondary join | Specify secondary join conditions in many to many relationships when you cannot decide for yourself in SQLAlchemy |
There are descriptions of many basic options above. Let's add, delete and modify the database to enhance understanding.
Basic operation of database
In flask Sqlalchemy, insert, modify and delete operations are managed by the database session. Session dB Session representation. Before you write the data to the database, you first add the data to the session and then call the commit() method to submit the session.
Database session is to ensure data consistency and avoid data inconsistency caused by partial update. The commit operation writes all session objects into the database. If an error occurs in the writing process, the whole session will become invalid.
The database session can also be rolled back through dB session. The rollback () method implements the state before the session submits data.
In flask Sqlalchemy, query operation is to manipulate data through query object. The most basic query is to return all the data in the table. You can query the database more accurately through the filter.
Let's create the data model of two tables: user table and role table.
Define model classes in view functions
After reading so many concept descriptions above, let's take a look at how to create a data model and create a data table, as follows:
1. In script 15_SQLAlchemy.py writing to create User and Role data models
from flask import Flask from flask_sqlalchemy import SQLAlchemy import pymysql pymysql.install_as_MySQLdb() app = Flask(__name__) class Config(object): """configuration parameter""" # Set the URL to connect to the database user = 'root' password = '********' database = 'flask_ex' app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://%s:%s@127.0.0.1:3306/%s' % (user,password,database) # Set sqlalchemy to automatically track the database SQLALCHEMY_TRACK_MODIFICATIONS = True # The original SQL statement is displayed when querying app.config['SQLALCHEMY_ECHO'] = True # Prohibit automatic submission of data processing app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = False # Read configuration app.config.from_object(Config) # Create database sqlalchemy tool object db = SQLAlchemy(app) class Role(db.Model): # Define table name __tablename__ = 'roles' # Define field id = db.Column(db.Integer, primary_key=True,autoincrement=True) name = db.Column(db.String(64), unique=True) users = db.relationship('User',backref='role') # Reverses multiple User model objects associated with role s class User(db.Model): # Define table name __tablename__ = 'users' # Define field id = db.Column(db.Integer, primary_key=True,autoincrement=True) name = db.Column(db.String(64), unique=True, index=True) email = db.Column(db.String(64),unique=True) pswd = db.Column(db.String(64)) role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) # Set foreign keys if __name__ == '__main__': # Delete all tables db.drop_all() # Create all tables db.create_all()
- Execute the script and create the database
python3 15_SQLAlchemy.py
3. View the created table structure in mysql
mysql> show tables; +--------------------+ | Tables_in_flask_ex | +--------------------+ | roles | | users | +--------------------+ 2 rows in set (0.00 sec) mysql> mysql> desc users; +---------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(64) | YES | UNI | NULL | | | email | varchar(64) | YES | UNI | NULL | | | pswd | varchar(64) | YES | | NULL | | | role_id | int(11) | YES | MUL | NULL | | +---------+-------------+------+-----+---------+----------------+ 5 rows in set (0.00 sec) mysql> mysql> desc roles; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(64) | YES | UNI | NULL | | +-------+-------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec) mysql>
After creating the data table, let's see how to add, delete, query and modify the data.
Common SQLAlchemy query filters
filter | explain |
---|---|
filter() | Add the filter to the original query and return a new query |
filter_by() | Add the equivalent filter to the original query and return a new query |
limit | Use the specified value to limit the results returned by the original query |
offset() | Offset the result returned by the original query and return a new query |
order_by() | Sort the original query results according to the specified criteria and return a new query |
group_by() | Group the original query results according to the specified criteria and return a new query |
Common SQLAlchemy query executors
method | explain |
---|---|
all() | Returns all the results of the query as a list |
first() | Returns the first result of the query. If it is not found, it returns None |
first_or_404() | Returns the first result of the query. If it is not found, it returns 404 |
get() | Returns the row corresponding to the specified primary key. If it does not exist, returns None |
get_or_404() | Returns the row corresponding to the specified primary key. If it does not exist, it returns 404 |
count() | Number of returned query results |
paginate() | Returns a Paginate object that contains the results within the specified range |
Create table:
db.create_all()
Delete table
db.drop_all()
Insert a single piece of data at a time
if __name__ == '__main__': # Insert a role data role1 = Role(name='admin') db.session.add(role1) db.session.commit() # Insert another piece of data role2 = Role(name='user') db.session.add(role2) db.session.commit()
Execute script:
python3 15_SQLAlchemy.py
View the inserted data in mysql as follows:
mysql> select * from roles \G *************************** 1. row *************************** id: 1 name: admin *************************** 2. row *************************** id: 2 name: user 2 rows in set (0.00 sec)
Insert multiple pieces of data at one time
# Insert multiple pieces of data at one time user1 = User(name='wang',email='wang@163.com',pswd='123456',role_id=role1.id) user2 = User(name='zhang',email='zhang@189.com',pswd='201512',role_id=role2.id) user3 = User(name='chen',email='chen@126.com',pswd='987654',role_id=role2.id) user4 = User(name='zhou',email='zhou@163.com',pswd='456789',role_id=role1.id) db.session.add_all([user1,user2,user3,user4]) db.session.commit()
Insert data as follows:
python3 15_SQLAlchemy.py
Query the inserted data in mysql as follows:
mysql> select * from users \G *************************** 1. row *************************** id: 1 name: wang email: wang@163.com pswd: 123456 role_id: 1 *************************** 2. row *************************** id: 2 name: zhang email: zhang@189.com pswd: 201512 role_id: 2 *************************** 3. row *************************** id: 3 name: chen email: chen@126.com pswd: 987654 role_id: 2 *************************** 4. row *************************** id: 4 name: zhou email: zhou@163.com pswd: 456789 role_id: 1 4 rows in set (0.00 sec) mysql>
Although it seems that multiple pieces of data are inserted at one time in python, in fact, multiple line insertion statements are also executed in mysql. You can see the following from the mysql log:
2019-11-23T16:48:56.984459Z 9061 Query INSERT INTO users (name, email, pswd, role_id) VALUES ('wang', 'wang@163.com', '123456', 1) 2019-11-23T16:48:56.997132Z 9061 Query INSERT INTO users (name, email, pswd, role_id) VALUES ('zhang', 'zhang@189.com', '201512', 2) 2019-11-23T16:48:57.010175Z 9061 Query INSERT INTO users (name, email, pswd, role_id) VALUES ('chen', 'chen@126.com', '987654', 2) 2019-11-23T16:48:57.024134Z 9061 Query INSERT INTO users (name, email, pswd, role_id) VALUES ('zhou', 'zhou@163.com', '456789', 1)
In fact, multiple values are not merged into one insert statement, and multiple insert statements are still inserted one by one.
Query: filter_by exact query
Returns all user s whose name is equal to wang
User.query.filter_by(name='wang').all()
In the interaction model, execute the following:
>python3 db_demo.py shell In [1]: from db_demo import User In [2]: User.query.filter_by(name='wang').all() Out[2]: [<User 1>] In [3]:
first() returns the first object queried
User.query.first()
The implementation is as follows:
In [3]: User.query.first() Out[3]: <User 1>
all() returns all the queried objects
User.query.all()
The implementation is as follows:
In [4]: User.query.all() Out[4]: [<User 1>, <User 2>, <User 3>, <User 4>] In [5]:
filter fuzzy query, which returns all data with g at the end of the name.
User.query.filter(User.name.endswith('g')).all()
The implementation is as follows:
In [5]: User.query.filter(User.name.endswith('g')).all() Out[5]: [<User 1>, <User 2>]
get(), the parameter is the primary key. If the primary key does not exist, no content is returned
User.query.get()
The implementation is as follows:
In [6]: User.query.get(2) Out[6]: <User 2> In [7]: user2 = User.query.get(2) In [8]: user2.name Out[8]: 'zhang'
Logical non, return all data whose name is not equal to wang.
User.query.filter(User.name!='wang').all()
The implementation is as follows:
In [9]: User.query.filter(User.name!='wang').all() Out[9]: [<User 2>, <User 3>, <User 4>]
Logical and, and * needs to be imported, and all data satisfying the and * () condition is returned.
from sqlalchemy import and_ User.query.filter(and_(User.name!='wang',User.email.endswith('163.com'))).all()
The implementation is as follows:
In [10]: from sqlalchemy import and_ In [15]: users = User.query.filter(and_(User.name!='wang',User.email.endswith('163.com'))).all() In [16]: for user in users: ...: print(user.email) ...: zhou@163.com
Logical or, or needs to be imported_
from sqlalchemy import or_ User.query.filter(or_(User.name!='wang',User.email.endswith('163.com'))).all()
The implementation is as follows:
In [17]: from sqlalchemy import or_ In [18]: users = User.query.filter(or_(User.name!='wang',User.email.endswith('163.com'))).all() In [19]: for user in users: ...: print(user.name, user.email) ...: wang wang@163.com zhang zhang@189.com chen chen@126.com zhou zhou@163.com In [20]:
not_ Equivalent to negation
from sqlalchemy import not_ User.query.filter(not_(User.name=='chen')).all()
The implementation is as follows:
In [22]: from sqlalchemy import not_ In [25]: users = User.query.filter(not_(User.name=='chen')).all() In [26]: for user in users: ...: print(user.name, user.email) ...: wang wang@163.com zhang zhang@189.com zhou zhou@163.com
Delete after querying data
user = User.query.first() db.session.delete(user) db.session.commit() User.query.all()
The implementation is as follows:
(venv) $ >python3 db_demo.py shell In [1]: from db_demo import User In [3]: user = User.query.first() In [5]: from db_demo import db In [6]: db.session.delete(user) In [7]: db.session.commit() In [8]: User.query.all() Out[8]: [<User 2>, <User 3>, <User 4>]
Update data
user = User.query.first() user.name = 'dong' db.session.commit() User.query.first()
The implementation is as follows:
In [1]: from db_demo import User In [5]: from db_demo import db In [9]: user = User.query.first() In [10]: user Out[10]: <User 2> In [11]: user.name Out[11]: 'zhang' In [12]: user.name = 'dong' In [13]: db.session.commit() In [14]: user = User.query.first() In [15]: user.name Out[15]: 'dong'
Using update
User.query.filter_by(name='zhang').update({'name':'li'})
The implementation is as follows:
In [21]: User.query.filter_by(name='dong').update({'name':'li'}) Out[21]: 0 In [22]: User.query.get(2) Out[22]: <User 2> In [23]: user = User.query.get(2) In [24]: user.name Out[24]: 'li'
Example of association query: the relationship between roles and users is a one to many relationship. A role can have multiple users, and a user can only belong to one role.
All users associated with the query role:
#Query the roles whose table id is 1 role1 = Role.query.get(1) #Query all users in this role role1.users
The implementation is as follows:
In [25]: from db_demo import Role In [26]: role1 = Role.query.get(1) In [27]: role1.users Out[27]: [<User 4>] In [28]: role2 = Role.query.get(2) In [29]: role2.users Out[29]: [<User 2>, <User 3>]
Role of association query user:
#Query the users with id 3 in the users table user1 = User.query.get(3) #Query the user's role user1.role
The implementation is as follows:
In [30]: user1 = User.query.get(3) In [31]: user1.role Out[31]: <Role 2>