zoukankan      html  css  js  c++  java
  • flask——简单博客示例教程(三)

    原文:https://blog.csdn.net/u014793102/article/category/9285123

    Flask从入门到做出一个博客的大型教程(三)

    在开始之前,先来看下项目的整体结构。

     1 flask
     2 ├── app
     3 │   ├── forms.py
     4 │   ├── __init__.py
     5 │   ├── routes.py
     6 │   └── templates
     7 │       ├── base.html
     8 │       ├── index.html
     9 │       └── login.html
    10 ├── config.py
    11 ├── myblog.py

    4 数据库

    对于一个完整的网站数据库是很重要的,因为你的数据得有位置读取呀,网上很多数据库都用的sqlite,但是,我想使用mysql,所以接下来咱们就以mysql为数据库来讲解喽。

    1 (venv) duke@coding:~/flask_tutorial/flask$ pip install flask-sqlalchemy

    这样就可以对数据库进行操作了,但是实际项目中会经常对数据库进行修改,但是一般不会手动的去数据库里进行改动,通常的做法是修改ORM对应的模型,然后再把模型映射到数据库中。在flask里有一个集成的工具是专门做这个事情的,安装它。

    1 (venv) duke@coding:~/flask_tutorial/flask$ pip install flask-migrate

    因为我使用的是MySQL数据库,而在python3中不再支持mysqldb,因此我们还需要安装pymysql.

    1 (venv) duke@coding:~/flask_tutorial/flask$ pip install pymysql

    需要的组件都安装好了,接下来在配置文件里配置数据库。

    app/config.py : 使用配置文件config.py中的内容

    1 import os
    2 BASE_DIR = os.path.abspath(os.path.dirname(__file__))
    3 class Config(object):
    4     #.......
    5     #格式为mysql+pymysql://数据库用户名:密码@数据库地址:端口号/数据库的名字?数据库格式
    6     SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:123456@localhost:3306/flaskblog?charset=utf8'
    7     #如果你不打算使用mysql,使用这个连接sqlite也可以
    8     #SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(BASE_DIR,'app.db')
    9     SQLALCHEMY_TRACK_MODIFICATIONS = False

    配置文件设置好了以后,就要对初始化文件进行修改。

    app/_ _ init_ _.py : 数据库的初始化设置

     1 from flask import Flask
     2 from config import Config
     3 from flask_sqlalchemy import SQLAlchemy
     4 from flask_migrate import Migrate
     5 app = Flask(__name__)
     6 app.config.from_object(Config)
     7 #建立数据库关系
     8 db = SQLAlchemy(app)
     9 #绑定app和数据库,以便进行操作
    10 migrate = Migrate(app,db)
    11 
    12 from app import routes,models

    接下来比较重要的就是设计模型了,model是模型的映射,只有设计好model才能进行一系列的操作。新建一个models.py文件。

    1 (venv) duke@coding:~/flask_tutorial/flask$ touch app/models.py

    app/models.py : 用户数据库模型

     1 from app import db
     2 
     3 class User(db.Model):
     4     __tablename__ = 'user'
     5     id = db.Column(db.Integer,primary_key=True)
     6     username = db.Column(db.String(64),index=True,unique=True)
     7     email = db.Column(db.String(120),index=True,unique=True)
     8     password_hash = db.Column(db.String(128))
     9 
    10     def __repr__(self):
    11         return '<用户名:{}>'.format(self.username)

    对模型进行验证:

    1 (venv) duke@coding:~/flask_tutorial/flask$ python
    2 Python 3.6.4 (default, May  3 2018, 19:35:55) 
    3 [GCC 5.4.0 20160609] on linux
    4 Type "help", "copyright", "credits" or "license" for more information.
    5 >>> from app.models import User
    6 >>> u = User(username='duke',email='duke@126.com')
    7 >>> u
    8 <用户名:duke>

    对模型验证后,发现是正确的,进行数据库初始化。

    1 (venv) duke@coding:~/flask_tutorial/flask$ flask db init
    2   Creating directory /home/duke/flask_tutorial/flask/migrations ... done
    3   Creating directory /home/duke/flask_tutorial/flask/migrations/versions ... done
    4   Generating /home/duke/flask_tutorial/flask/migrations/script.py.mako ... done
    5   Generating /home/duke/flask_tutorial/flask/migrations/alembic.ini ... done
    6   Generating /home/duke/flask_tutorial/flask/migrations/README ... done
    7   Generating /home/duke/flask_tutorial/flask/migrations/env.py ... done
    8   Please edit configuration/connection/logging settings in
    9   '/home/duke/flask_tutorial/flask/migrations/alembic.ini' before proceeding.

    现在看一看项目结构

     1 flask
     2 ├── app
     3 │   ├── forms.py
     4 │   ├── __init__.py
     5 │   ├── models.py
     6 │   ├── routes.py
     7 │   └── templates
     8 │       ├── base.html
     9 │       ├── index.html
    10 │       └── login.html
    11 ├── config.py
    12 ├── migrations
    13 │   ├── alembic.ini
    14 │   ├── env.py
    15 │   ├── README
    16 │   ├── script.py.mako
    17 │   └── versions
    18 ├── myblog.py

    接下来创建数据库的管理工具。

    1 (venv) duke@coding:~/flask_tutorial/flask$ flask db migrate -m 'users_table'
    2 INFO  [alembic.runtime.migration] Context impl MySQLImpl.
    3 INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
    4 INFO  [alembic.autogenerate.compare] Detected added table 'user'
    5 INFO  [alembic.autogenerate.compare] Detected added index 'ix_user_email' on '['email']'
    6 INFO  [alembic.autogenerate.compare] Detected added index 'ix_user_username' on '['username']'
    7   Generating
    8   /home/duke/flask_tutorial/flask/migrations/versions/06ea43ff4439_users_table.py
    9   ... done

    创建数据库的中的表。

    1 (venv) duke@coding:~/flask_tutorial/flask$ flask db upgrade
    2 INFO  [alembic.runtime.migration] Context impl MySQLImpl.
    3 INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
    4 INFO  [alembic.runtime.migration] Running upgrade  -> 06ea43ff4439, users_table

    执行到这里,表已经在数据库中建立完成。或许你会问,这和我以前的接触过的不一样啊,这么会麻烦这么多,因为你对数据库模型修改后,可以很方便的进行数据库表的迁移,这会大大的减少以后可能会发生的大量的工作量。

    网站里不可能只有一张表的,多张表之间肯定会有联系,接下来对表之间的关系进行一个详细介绍。

    app/models.py : 添加一张新表,并建立关系

     1 from datetime import datetime
     2 from app import db
     3 
     4 class User(db.Model):
     5     __tablename__ = 'user'
     6     id = db.Column(db.Integer,primary_key=True)
     7     username = db.Column(db.String(64),index=True,unique=True)
     8     email = db.Column(db.String(120),index=True,unique=True)
     9     password_hash = db.Column(db.String(128))
    10     # back是反向引用,User和Post是一对多的关系,backref是表示在Post中新建一个属性author,关联的是Post中的user_id外键关联的User对象。
    11     #lazy属性常用的值的含义,select就是访问到属性的时候,就会全部加载该属性的数据;joined则是在对关联的两个表进行join操作,从而获取到所有相关的对象;dynamic则不一样,在访问属性的时候,并没有在内存中加载数据,而是返回一个query对象, 需要执行相应方法才可以获取对象,比如.all()
    12     posts = db.relationship('Post',backref='author',lazy='dynamic')
    13 
    14     def __repr__(self):
    15         return '<用户名:{}>'.format(self.username)
    16 
    17 class Post(db.Model):
    18     __tablename__ = 'post'
    19     id = db.Column(db.Integer,primary_key=True)
    20     body = db.Column(db.String(140))
    21     timestamp = db.Column(db.DateTime,index=True,default=datetime.utcnow)
    22     user_id = db .Column(db.Integer,db.ForeignKey('user.id'))
    23 
    24     def __repr__(self):
    25         return '<Post {}>'.format(self.body)

    生成新的数据库关系:

    1 (venv) duke@coding:~/flask_tutorial/flask$ flask db migrate -m 'posts_table'
    2 INFO  [alembic.runtime.migration] Context impl MySQLImpl.
    3 INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
    4 INFO  [alembic.autogenerate.compare] Detected added table 'post'
    5 INFO  [alembic.autogenerate.compare] Detected added index 'ix_post_timestamp' on '['timestamp']'
    6   Generating /home/miguel/microblog/migrations/versions/780739b227a7_posts_table.py ... done

    提交到数据库中:

    1 (venv) duke@coding:~/flask_tutorial/flask$ flask db upgrade
    2 INFO  [alembic.runtime.migration] Context impl MySQLImpl.
    3 INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
    4 INFO  [alembic.runtime.migration] Running upgrade  -> 780739b227a7, posts_table

    接下来使用shell对进行操作:

    1 (venv) duke@coding:~/flask_tutorial/flask$ python
    2 Python 3.6.4 (default, May  3 2018, 19:35:55) 
    3 [GCC 5.4.0 20160609] on linux
    4 Type "help", "copyright", "credits" or "license" for more information.
    5 >>> from app import db
    6 >>> from app.models import User,Post

    在用户表中添加一条用户信息:

    1 #创建一个User对象实例
    2 >>> u = User(username='duke',email='duke@126.com')
    3 #将实例添加
    4 >>> db.session.add(u)
    5 #提交
    6 >>> db.session.commit()

    查看数据库后发现,插进一条数据。

    在用户表中添加另外一条用户信息:

    1 >>> u = User(username='king',email='king@qq.com')
    2 >>> db.session.add(u)
    3 >>> db.session.commit()

    通过查询数据库发现也插进了一条数据,但是怎么查询的呢?

    查询数据库中信息:

    1 >>> users = User.query.all()
    2 >>> users
    3 [<用户名:duke>, <用户名:king>]
    4 >>> for u in users:
    5 ...     print(u.id,u.username)
    6 ... 
    7 1 duke
    8 2 king

    这是一次性全部查询,那能不能查单条数据呢?答案是肯定的喽。

    1 #根据id可以查询到数据
    2 >>> u = User.query.get(2)
    3 >>> u
    4 <用户名:king>

    普通的数据库表咱们会了,那么有外键关联的一对多中数据库表怎么插入数据呢?

     1 #查找到一个User对象
     2 >>> u = User.query.get(1)
     3 #将该User对象与Post建立关系
     4 >>> p = Post(body='我第一次提交数据!',author=u)
     5 >>> db.session.add(p)
     6 >>> db.session.commit()
     7 #插入第二条数据,但是拥有者都是同一个人
     8 >>> p = Post(body='我第二次提交数据了!',author=u)
     9 >>> db.session.add(p)
    10 >>> db.session.commit()

    现在通过查询来让你更加的熟悉一对多的关系。

     1 # 获得一个用户的所有提交
     2 >>> u = User.query.get(1)
     3 >>> u
     4 <用户名:duke>
     5 #u.posts.all()中的posts是model中的,User和Post关联的作用。
     6 >>> posts = u.posts.all()
     7 >>> posts
     8 [<Post 我第一次提交数据!>, <Post 我第二次提交数据了!>]
     9 
    10 #进行相同的操作,但是换成另外一名用户
    11 >>> u = User.query.get(2)
    12 >>> u
    13 <用户名:king>
    14 >>> u.posts.all()
    15 []
    16 
    17 #对所有的posts进行查询
    18 >>> posts = Post.query.all()
    19 >>> for p in posts:
    20 ...     print(p.id,p.author.username,p.body)
    21 ... 
    22 1 duke 我第一次提交数据!
    23 2 duke 我第二次提交数据了!
    24 
    25 #还可以按照一定的规则进行查询
    26 >>> User.query.order_by(User.username.desc()).all()
    27 [<用户名:king>, <用户名:duke>]

    熟悉了查询,接下来就把刚才的测试数据都删除吧!

    1 >>> users = User.query.all()
    2 >>> for u in users:
    3 ...     db.session.delete(u)
    4 ... 
    5 >>> posts = Post.query.all()
    6 >>> for p in posts:
    7 ...     db.session.delete(p)
    8 ... 
    9 >>> db.session.commit()
    本博客为记录本人遇到问题时所找到的解决方案,且均经过本人亲测可用,如有侵权请联系添加来源或删除文章,谢谢。
  • 相关阅读:
    关于js计算非等宽字体宽度的方法
    [NodeJs系列]聊一聊BOM
    Vue.js路由管理器 Vue Router
    vue 实践技巧合集
    微任务、宏任务与Event-Loop
    事件循环(EventLoop)的学习总结
    Cookie、Session和LocalStorage
    MySQL 树形结构 根据指定节点 获取其所在全路径节点序列
    MySQL 树形结构 根据指定节点 获取其所有父节点序列
    MySQL 创建函数报错 This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators
  • 原文地址:https://www.cnblogs.com/heymonkey/p/11721257.html
Copyright © 2011-2022 走看看