常用Flask的插件bootstrap wtf sqlalchemy migrate及script

flask_bootstrap

  1. 如何在flask中使用Boostrap?
    要想在程序中集成Bootstrap,显然要对模板做所有必要的改动。不过,更简单的方法是使用一个名为Flask-Bootstrap 的Flask 扩展,简化集成的过程。Flask-Bootstrap 使用pip安装:
pip install flask_bootstrap
  1. Flask 扩展一般都在创建程序实例时初始化,下面是Flask_Bootstrap的初始化方法:
from flask_bootstrap import  Bootstrap
app = Flask(__name__)
bootstrap = Bootstrap(app)

初始化Flask-Bootstrap 之后,就可以在程序中使用一个包含所有Bootstrap 文件的基模板。这个模板利用Jinja2 的模板继承机制,让程序扩展一个具有基本页面结构的基模板,其中就有用来引入Bootstrap 的元素。

  1. 如何引用bootatrap的基模板?
{%extends "bootstrap/base.html"%}
{%block title %}Flask{% endblock %}

这两个块分别表示页面中的导航条和主体内容。在这个模板中,navbar 块使用Bootstrap 组件定义了一个简单的导航条。content 块中有个

容器,其中包含一个页面头部。

  1. Flask-Bootstrap定义的其他可用块:
    参考链接: https://pythonhosted.org/Flask-Bootstrap/basic-usage.html#available-blocks
    块名   说明
    doc 整个html文档
    html_attribs html标签属性
    html   html标签中的内容
    head head标签中的内容
    title title标签中的内容
    metas 一组meta标签
    styles 层叠样式表定义
    body_attribs body标签的属性
    body body标签中的内容
    navbar 用户定义的导航条
    content 用户定义的页面内容
    scripts 文档底部的JavaScript 声明

  2. 如何继承原有内容:
      上表中的很多块都是Flask-Bootstrap 自用的,如果直接重定义可能会导致一些问题。例如,Bootstrap 所需的文件在styles 和scripts 块中声明。如果程序需要向已经有内容的块中添加新内容,必须使用Jinja2 提供的super() 函数。例如,如果要在衍生模板中添加新的JavaScript 文件,需要这么定义scripts 块:

{% block scripts %}
{{ super() }}
<script type="text/javascript" src="my-script.js"></script>
{% endblock %}

首先了解一下bootstrap提供了多少block,bootstrap中的base.html如下:

{% block doc -%}       ###doc:整个HTML文档(开始)
<!DOCTYPE html>        
<html{% block html_attribs %}{% endblock html_attribs %}>###html_attribs:<html>标签的属性
{%- block html %}     ###html:<html>标签中的内容(开始)
  <head>
    {%- block head %}  ###head:<head>标签中的内容(开始)
    <title>{% block title %}{{title|default}}{% endblock title %}</title> ###title:<title>标签中的内容

    {%- block metas %} ###metas:一组<meta>标签
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    {%- endblock metas %}

    {%- block styles %}   ##styles:层叠样式表定义
    <!-- Bootstrap -->
    <link href="{{bootstrap_find_resource('css/bootstrap.css', cdn='bootstrap')}}" rel="stylesheet">
    {%- endblock styles %}
    {%- endblock head %}     ###head:<head>标签中的内容(结束)
  </head>               ###body_attribs:<body>标签的属性
  <body{% block body_attribs %}{% endblock body_attribs %}>
    {% block body -%}      ###body:<body>标签中的内容(开始)
    {% block navbar %}     ###navbar:用户定义的导航条
    {%- endblock navbar %}
    {% block content -%}    ###content:用户定义的页面内容
    {%- endblock content %}

    {% block scripts %}  ###scripts:文档底部的JavaScript声明
    <script src="{{bootstrap_find_resource('jquery.js', cdn='jquery')}}"></script>
    <script src="{{bootstrap_find_resource('js/bootstrap.js', cdn='bootstrap')}}"></script>
    {%- endblock scripts %}
    {%- endblock body %} ###body:<body>标签中的内容(结束)
  </body>
{%- endblock html %}     ###html:<html>标签中的内容(结束)
</html>
{% endblock doc -%}      ###doc:整个HTML文档(结束)

flask_wtf

  1. 为什么使用Flask-WTF?
    request对象公开了所有客户端发送的请求信息。特别是request.form可以访问POST请求提交的表单数据。
    尽管Flask的request对象提供的支持足以处理web表单,但依然有许多任务会变得单调且重复。
    表单的HTML代码生成和验证提交的表单数据就是两个很好的例子。
    优势:
    Flask-WTF扩展使得处理web表单能获得更愉快的体验。该扩展是一个封装了与框架无关的WTForms包的Flask集成。

  2. 什么是表单处理?
    在网页中,为了和用户进行信息交互总是不得不出现一些表单。
    flask设计了WTForm表单库来使flask可以更加简便地管理操作表单数据。
    WTForm中最重要的几个概念如下:

    1). Form类,开发者自定义的表单必须继承自Form类或者其子类。
    Form类最主要的功能是通过其所包含的Field类提供对表单内数据的快捷访问方式。
      2). 各种Field类,即字段。一般而言每个Field类都对应一个input的HTML标签。
    比如WTForm自带的一些Field类比如BooleanField就对应,
    SubmitField就对应等等。
      3). Validator类。这个类用于验证用户输入的数据的合法性。
    比如Length验证器可以用于验证输入数据的长度,
    FileAllowed验证上传文件的类型等等。

另外,flask为了防范csfr(cross-site request forgery)攻击,
默认在使用flask-wtf之前要求app一定要设置过secret_key。
最简单地可以通过app.config[‘SECRET_KEY’] = 'xxxx’来配置。

  1. 常见的Field类

PasswordField   密码字段,自动将输入转化为小黑点

DateField   文本字段,格式要求为datetime.date一样

IntergerField   文本字段,格式要求是整数

DecimalField   文本字段,格式要求和decimal.Decimal一样

FloatField   文本字段,值是浮点数

BooleanField   复选框,值为True或者False

RadioField   一组单选框

SelectField   下拉列表,需要注意一下的是choices参数确定了下拉选项,
但是和HTML中的 标签一样,其是一个tuple组成的列表,
可以认为每个tuple的第一项是选项的真正的值,而第二项是alias。

MultipleSelectField  可选多个值的下拉列表

  1. Validator是验证函数:

    Validator是验证函数,把一个字段绑定某个验证函数之后,flask会在接收表单中的数据之前对数据做一个验证,
    如果验证成功才会接收数据。验证函数Validator如下,具体的validator可能需要的参数不太一样,这里只给出
    一些常用的,更多详细的用法可以参见wtforms/validators.py文件的源码,参看每一个validator类需要哪些参数:

*基本上每一个validator都有message参数,指出当输入数据不符合validator要求时显示什么信息。

Email  验证电子邮件地址的合法性,要求正则模式是.+@([.@][^@]+)$

EqualTo  比较两个字段的值,通常用于输入两次密码等场景,可写参数fieldname,不过注意其是一个字符串变量,指向同表单中的另一个字段的字段名

IPAddress  验证IPv4地址,参数默认ipv4=True,ipv6=False。如果想要验证ipv6可以设置这两个参数反过来。

Length  验证输入的字符串的长度,可以有min,max两个参数指出要设置的长度下限和上限,注意参数类型是字符串,不是INT!!

NumberRange  验证输入数字是否在范围内,可以有min和max两个参数指出数字上限下限,注意参数类型是字符串,不是INT!!然后在这个validator的message参数里可以设置%(min)s和%(max)s两个格式化部分,来告诉前端这个范围到底是多少。其他validator也有这种类似的小技巧,可以参看源码。

Optional  无输入值时跳过同字段的其他验证函数

Required  必填字段

Regexp  用正则表达式验证值,参数regex=‘正则模式’

URL  验证URL,要求正则模式是[a-z]+://(?P<host>[/:]+)(?P:[0-9]+)?(?P /.*)?$

AnyOf  确保值在可选值列表中。参数是values(一个可选值的列表)。特别提下,和SelectField进行配合使用时,不知道为什么SelectField的choices中项的值不能是数字。。否则AnyOf的values参数中即使有相关数字也无法识别出当前选项是合法选项。我怀疑NoneOf可能也是一样的套路。

NoneOf  确保值不在可选值列表中

 flask-bootstrap(添加css, js样式)---提供了base.html, wtf.html
 flask-wtf(表单处理)-
 表单类型(StringField, PasswordField, SubmitField, FileField)
 验证表单(DataRequired, Length, Email, Regexp, EqualTo)

eg:
wtflogin.htm:

{% extends 'bootstrap/base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block content %}
<form method="POST" action="/login/">
    {{ wtf.quick_form(form) }}
    {% if message %}
        <p style="color:red">{{ message }}</p>
    {% endif %}
</form>
{% endblock %}

run.py:

import random
from flask import Flask, redirect, render_template, flash
from forms import LoginForm
from flask_bootstrap import  Bootstrap
app = Flask(__name__)
bootstrap = Bootstrap(app)
app.config['SECRET_KEY'] =  random._urandom(24)
@app.route('/success/')
def success():
    return  "success"
@app.route('/login/', methods=('GET', 'POST'))
def submit():
    # 实例化表单对象;
    form = LoginForm()
     # 如果是post方法并且表单验证通过的话, 返回True;
    if form.validate_on_submit():
        return redirect('/success/')
    return render_template('wtflogin.html', form=form)
app.run(port=9001)

forms

from flask_wtf import FlaskForm
from flask_wtf.file import FileRequired, FileAllowed
from wtforms import StringField, PasswordField, SubmitField, FileField
from wtforms.validators import DataRequired, Length
class LoginForm(FlaskForm):
    name = StringField(
        label="用户名/邮箱/手机号",
        validators=[
             DataRequired(message="请输入用户名"),
            Length(3, 10, message="长度不符"),
        ]

    )
    passwd = PasswordField(
        label="密码",
        validators=[
             DataRequired(message="输入密码"),
            Length(3, 10,message="长度不符")
        ] )

    file = FileField(
        label="头像",
        validators=[
            FileRequired(),
            FileAllowed(['png', 'jpg'],message='文件非图片')
        ]
    )
    sumbit = SubmitField(
        label="登陆"
    )

在这里插入图片描述

flask_sqlalchemy

flask_sqlalchemy-------关于数据库操作的文件,通过创建类的方法实现数据库操作,实际是将python的代码转换为数据库语句。
sqlchemy支持的字段类型:
在这里插入图片描述
sqlchemy支持的字段限制:
在这里插入图片描述
查询过路器:
在这里插入图片描述
执行函数:
在这里插入图片描述
分页对象属性:
在这里插入图片描述
分页对象拥有的方法:
在这里插入图片描述

from datetime import datetime

import pymysql
# 关于数据库操作的文件
from flask_sqlalchemy import SQLAlchemy
from flask import Flask
from sqlalchemy import desc

app = Flask(__name__)
#用于连接数据的数据库。mysql://username:password@server/db
app.config['SQLALCHEMY_DATABASE_URI']='mysql+pymysql://cooffee:cooffee@172.25.254.78/user'
# SQLAlchemy 将会追踪对象的修改并且发送信号。
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=True
db = SQLAlchemy(app)
# 默认情况下创建一个表, 表名为类名; 如果指定了__tablename__, 那么表名为你指定的名称;
class Student(db.Model):
    _tablename_='students'
     # sid: 表头的一列, db.SMALLINT代表存储的数据类型, primary_key(主键), 数据是唯一的;
    sid = db.Column(db.SMALLINT,primary_key=True)
    sname = db.Column(db.String(50))
    sage = db.Column(db.SMALLINT)

#  实现一对多(Role(1): User(n))的关系
#    多的一端写外键
#    少的一端写反向引用
class User(db.Model):
    # autoincrement=True自增
    id = db.Column(db.INTEGER,autoincrement=True,primary_key=True)
     #  unique=True, name的值不能重复, 是唯一的;
    name = db.Column(db.String(50),unique=True)
    # 长度为100, 是因为网站密码一般会加密;
    passwd = db.Column(db.String(100))
    # 指定用户注册/创建的时间,
    # default, 指定默认值, datetime.now()获取当前时间;
    # 用户注册时间为当前时间;
    add_time = db.Column(db.DateTime,default=datetime.now())
    # 用户的角色id,不能随便写, 必须要关联其他的数据库表(role) --- 外键
    role_id = db.Column(db.INTEGER,db.ForeignKey('role.id'))
    def __repr__(self):
        return '<User:%s>' %(self.name)
class Role(db.Model):
    id = db.Column(db.INTEGER, autoincrement=True, primary_key=True)
    name = db.Column(db.String(50), unique=True)
     #  Role表中的users属性与User表关联, 并且User这个表中可以由role这个对象属性;
    users = db.relationship('User',backref='role')
    def __repr__(self):
        return '<Role:%s>' %(self.name)
if __name__=='__main__':
    #   删除定义的表结构    db.drop_all()
    #  创建定义的表结构
    db.create_all()
    #往表中插入数据
    #		创建Python对象
    #		把它添加到会话
    #		提交会话
    role1 = Role(name='超级会员')
    role2 = Role(name='会员')
    db.session.add(role1)
    db.session.add(role2)
    db.session.commit()
    #添加20个用户,其中10个为超级会员, 10个为会员;
    for i in range(10):
        u = User(name='cooffee%s' %(i),passwd='cooffee',role_id=1)
        db.session.add(u)
    db.session.commit()
    for i in range(10):
        u = User(name='floating%s' %(i),passwd='floating',role_id=2)
        db.session.add(u)
    db.session.commit()
    #  查询所有数据
    print(User.query.all())
    print(Role.query.all())
    # 根据条件查询数据(筛选数据(filter_by)); slect * from table where xxx=xxx;
    print(User.query.filter_by(role_id=1).all())
    print(User.query.filter_by(role_id=2).all())
    # 对于找到的内容进行更新
    u = User.query.filter_by(name='cooffee0').first()
    print(u)
    u.passwd='123456'
    db.session.add(u)
    db.session.commit()
    #筛选数据方法2(filter)
    # 通过这种方式可以查看原生的sql语句
    user = User.query.filter(User.role_id==1)
    print(user)
    # 对于查询的信息进行显示限制;
    users = User.query.filter_by(role_id=1).limit(5).all()
    print(users,len(users),end='\n')
    # 对于查询的信息进行排序输出(默认情况由小到大进行排序), 如果想要由大到小: desc(User.add_time);
    users = User.query.filter_by(role_id=1).order_by(desc(User.add_time)).all()
    print(users)
    # 多个过滤函数加一个显示函数
    # #  offset指定偏移量, limit 指定输出数量, 类似于切片操作;
    # #  1 2 3 4 5 6 7 8 9
    # # limit(5): 1 2 3 4 5
    # # limit(5).offset(2): 3 4 5 6 7
    users = User.query.filter_by(role_id=1).order_by(desc(User.add_time)).limit(5).all()
    print(users)
    users = User.query.filter_by(role_id=1).order_by(desc(User.add_time)).limit(5).offset(2).all()
    print(users)
    # # 切片操作li[2:7]
    count = User.query.filter_by(role_id=1).order_by(desc(User.add_time)).slice(2,7).count()
    print(count)
    #  分页:第一个参数代表显示第几页的数据, 第二个参数代表每页显示多少条数据;
    users = User.query.paginate(1,5)
    print(users.items)
    users = User.query.paginate(2,5)
    print(users.items)
    #  反向引用的使用
   u = User.query.filter_by(name='westos0').first()
   print(u.name, u.passwd, u.add_time, u.role_id, u.role, u.role.id, u.role.name)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

flask_migrate及flask_script

Flask-Migrate是用于处理SQLAlchemy 数据库迁移的扩展工具。当Model出现变更的时候,通过migrate去管理数据库变更。
Flask Script扩展提供向Flask插入外部脚本的功能,包括运行一个开发用的服务器,一个定制的Python shell,设置数据库的脚本,cronjobs,及其他运行在web应用之外的命令行任务;使得脚本和系统分开;

# 1). 创建迁移仓库(migrations目录)
python script.py  db init
# 2). 读取类的内容, 生成版本文件,  并没有真正在数据库中添加或删除;
python  script.py  db migrate -m "添加性别"
# 3). 在数据库中曾删改;
python script.py  db upgrade
# 4). 检测是否成功?
mysql -ucooffee -p
# 5). 去查看改变的历史状态;
python script.py  db history
# 6). 返回指定的版本状态;
python script.py  db downgrade  base

在modles.py文件里边的User类添加gender即在数据库中user表添加gender属性:
modles.py:

class User(db.Model):
    id = db.Column(db.INTEGER,autoincrement=True,primary_key=True)
    name = db.Column(db.String(50),unique=True)
    passwd = db.Column(db.String(100))
    #添加的属性
    gender = db.Column(db.Boolean, default=True)
    add_time = db.Column(db.DateTime,default=datetime.now())
    role_id = db.Column(db.INTEGER,db.ForeignKey('role.id'))
    def __repr__(self):
        return '<User:%s>' %(self.name)

在这里插入图片描述

python manage.py db init:
在这里插入图片描述

在这里插入图片描述

python manage.py db migrate -m “添加性别” :
python manage.py db upgrade:
在这里插入图片描述

在这里插入图片描述

添加自定义命令的3中方式:
定义Command的子类;
使用command装饰器
使用option装饰器

manage.py:

from flask_migrate import Migrate,MigrateCommand
from  flask_script import Shell, Manager, Command
from models import app,db,User,Role
# 用来管理命令的对象, Manager用来跟踪所有名林不过并处理他们如何从命令行调用;
manager = Manager(app)
migrate = Migrate(app,db)
# 添加一条数据库管理的命令
manager.add_command('db',MigrateCommand)

#使用command装饰器
@manager.command
def showUser():
    """显示所有的用户"""
    users = User.query.all()
    print(users[:5])

#定义Command的子类;
class showRole(Command):
    """显示所有角色"""
    def run(self):
        print(Role.query.all())
manager.add_command('showRole',showRole)

#使用option装饰器 入符哦命令需要添加参数时
# -n 简写, --name, 全称,
@manager.option('-n','--name',help="新建用户的名称")
@manager.option('-p','--passwd',help="新建用户密码")
def add_user(name,passwd):
    """创建用户"""
    try:
        user1 = User(name=name,passwd=passwd)
        db.session.add(user1)
        db.session.commit()
    except Exception as e:
        print("创建用户失败!",e)
    else:
        print("创建用户%s成功!" %(name))
#  实现添加用户的命令
if __name__=='__main__':
    manager.run()

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

用这及个插件简化及完善news

目录结构

在这里插入图片描述

各个py及html文件内容:
models.py:
import random
import pymysql
from datetime import datetime
from flask_bootstrap import Bootstrap
from  flask_sqlalchemy import  SQLAlchemy
from  flask import Flask
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI']='mysql+pymysql://cooffee:cooffee@172.25.254.78/usernews'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
app.config['SECRET_KEY']=random._urandom(24)
boostrap = Bootstrap(app)

class User(db.Model):
    id = db.Column(db.Integer, autoincrement=True, primary_key=True)
    name = db.Column(db.String(50), unique=True)
    passwd = db.Column(db.String(100))
    add_time = db.Column(db.DateTime, default=datetime.now())
    gender = db.Column(db.Boolean, default=True)
    role_id = db.Column(db.INTEGER, db.ForeignKey('role.id'))
    def __repr__(self):
        return '<User:%s>' %(self.name)

class Role(db.Model):
    id = db.Column(db.Integer, autoincrement=True, primary_key=True)
    name = db.Column(db.String(50), unique=True)
    users = db.relationship('User',backref='role')
    def __repr__(self):
        return  "<Role:%s>" %(self.name)

if __name__=="__main__":
    db.drop_all()
    db.create_all()
    role1 = Role(name="超级会员")
    role2 = Role(name="会员")
    db.session.add(role1)
    db.session.add(role2)
    db.session.commit()
    user = User(name='root',passwd='root',role_id=1)
    db.session.add(user)
    db.session.commit()

在这里插入图片描述

manage.py:
from flask_migrate import Migrate,MigrateCommand
from  flask_script import Shell, Manager, Command
from models import app,db,User,Role
# 用来管理命令的对象, Manager用来跟踪所有名林不过并处理他们如何从命令行调用;
manager = Manager(app)
migrate = Migrate(app,db)
# 添加一条数据库管理的命令
manager.add_command('db',MigrateCommand)

#使用command装饰器
@manager.command
def showUser():
    """显示所有的用户"""
    users = User.query.all()
    print(users[:5])

#定义Command的子类;
class showRole(Command):
    """显示所有角色"""
    def run(self):
        print(Role.query.all())
manager.add_command('showRole',showRole)

#使用option装饰器 入符哦命令需要添加参数时
# -n 简写, --name, 全称,
@manager.option('-n','--name',help="新建用户的名称")
@manager.option('-p','--passwd',help="新建用户密码")
def add_user(name,passwd):
    """创建用户"""
    try:
        #这里默认用户为会员
        user1 = User(name=name,passwd=passwd,role_id=2)
        db.session.add(user1)
        db.session.commit()
    except Exception as e:
        print("创建用户失败!",e)
    else:
        print("创建用户%s成功!" %(name))
#  实现添加用户的命令
if __name__=='__main__':
    manager.run()

在这里插入图片描述

forms.py:
from flask_wtf import FlaskForm
from wtforms import StringField,PasswordField,SubmitField,FileField
from wtforms.validators import DataRequired, Length, Regexp, EqualTo, Email
from  flask_wtf.file import FileRequired,FileAllowed
class LoginForm(FlaskForm):
    user = StringField(
        label="用户名/手机/邮箱",
        validators=[
            DataRequired(message="用户名不能为空"),
            Length(3,12,message="长度在3-12之间")
        ]
    )
    passwd = PasswordField(
        label="密码",
        validators=[
            Length(4,6,message="长度在4-6之间")
        ]
    )
    submit = SubmitField(
        label="登录"
    )
class RegisterForm(FlaskForm):
    user = StringField(
        label="用户名/手机/邮箱",
        validators=[
            DataRequired(message="用户名不能为空"),
            Length(3,12,message="长度在3-12之间")
        ]
    )
    passwd = PasswordField(
        label="密码",
        validators=[
            Length(4, 6, message="长度在4-6之间")
        ]
    )
    repasswd = PasswordField(
        label="确认密码",
        validators=[
            EqualTo('passwd',"两次密码输入不一致")
        ]
    )
    email = StringField(
        label="邮箱",
        validators=[
            Email("邮箱格式不正确!")
        ]
    )
    phone = StringField(
        label="电话",
        validators=[
            Regexp(r'1\d{10}',message="号码格式不正确!")
        ]
    )
    face = FileField(
        label="上传头像",
        validators=[
            FileAllowed(['png','jpg'],message="文件非图片")
        ]
    )
    submit = SubmitField(
        label="注册"
    )

run.py:
import random
import functools
import os
from datetime import datetime
from models import app, User, db
import psutil as psutil
from flask import Flask, request, render_template, redirect, url_for, abort, session
from forms import LoginForm,RegisterForm

def is_login(f):
    """判断用户是否登陆的装饰器"""
    @functools.wraps(f)
    def wrapper(*args,**kwargs):
        if 'user' not in session:
            return redirect(url_for('login'))
        return f(*args,**kwargs)
    return wrapper

# 用户主页
@app.route('/')
def index():
    return render_template('index.html')

# 用户登陆按钮
@app.route('/login/',methods=['GET','POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = form.data['user']
        passwd =form.data['passwd']
        u = User.query.filter_by(name=user).first()
        if u and passwd == u.passwd:
            session['user']=user
            session['passwd']=passwd
            return redirect(url_for('index'))
        else:
            return render_template('login.html',message='用户名或者密码错误',form=form)
    else:
        return render_template('login.html',form=form)
# 用户注销
@app.route('/logout/')
def logout():
    session.pop('user',None)
    session.pop('passwd',None)
    return redirect(url_for('index'))
# 用户注册
@app.route('/register/',methods=['GET','POST'])
def register():
    form = RegisterForm()
    if form.validate_on_submit():
        user = request.form['user']
        passwd = request.form['passwd']
        u = User.query.filter_by(name=user).first()
        if u:
            message = "用户已经存在"
            return render_template('signup.html',message=message)
        else:
            use = User(name=user,passwd=passwd,role_id=2)
            db.session.add(use)
            db.session.commit()
            return redirect(url_for('login'))
    else:
        return render_template('signup.html',form=form)

@app.route('/sysinfo/')
@is_login
def sysinfo():
    info = os.uname()
    boot_time = psutil.boot_time()
    boot_time = datetime.fromtimestamp(boot_time)
    now_time = datetime.now()
    delta_time = now_time - boot_time
    delta_time = str(delta_time).split('.')[0]
    return render_template('sysinfo.html',
                           hostname=info.nodename,
                           sysname=info.sysname,
                           release=info.release,
                           version= info.version,
                           machine=info.machine,
                           now_time=str(now_time).split('.')[0],
                           boot_time=boot_time,
                           delta_time=delta_time
                           )

@app.route('/userinfo/')
@is_login
def userinfo():
    users = User.query.all()
    return render_template("userinfo.html",users=users)
# 404异常处理: 类似于捕获异常
@app.errorhandler(404)
def not_found(e):
    return render_template('404.html')

app.run(port=9002)
base.html:
{% extends "bootstrap/base.html" %}
{% block head %}
    <title>{% block title %}首页{% endblock %} | cooffee</title>
    {% block styles %}
        {{super()}}
        <link rel="stylesheet" href="../static/css/main.css">
    {% endblock %}
{% endblock %}

{% block navbar %}
                     <!--导航栏-->
<nav class="navbar navbar-default">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="index.html"></a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active" style="padding-bottom: 15px;"><a href="index.html">首页<span class="sr-only">(current)</span></a></li>
        <li><a href="#">国内</a></li>
          <li><a href="#">数读</a></li>
          <li><a href="#">社会</a></li>
          <li><a href="/sysinfo/">系统信息</a></li>
          <li><a href="/userinfo/">登陆用户</a></li>
      </ul>
      <ul class="nav navbar-nav navbar-right">
          {% if 'user' in session %}
           <!--<li><a><span class="glyphicon glyphicon-user"></span></a></li>-->
           <li><a href="#">{{session.user}}</a></li>
           <li><a href="/logout/">注销</a></li>
          {% else %}
           <li><a href="/login/">登陆</a></li>
           <li><a href="/register/">注册</a></li>
          {% endif %}
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>
{% endblock %}

{% block content %}
    {% block newcontent %}

    {% endblock %}
    {% block footer %}
        <div class="footer">


                京ICP备11008151号京公网安备11010802014853


        </div>
    {% endblock %}
{% endblock %}

{% block scripts %}
{{super()}}
<script src="../static/js/bootstrap.min.js"></script>
{% endblock %}
index.html:
{% extends "base.html" %}

{% block title %}

{{super()}}

{% endblock %}

{% block newcontent %}
<div class="container container-fluid">
    <div class="row">
        <!--左侧导航-->
        <div class="col-xs-2">
            <div class="list-group left-side">
                <a class="list-group-item left-side-active" href="#">综合</a>
                <a class="list-group-item" href="#">电影</a>
                <a class="list-group-item" href="#">电视剧</a>
                <a class="list-group-item" href="#"> 明星</a>
                <a class="list-group-item" href="#">娱乐</a>
            </div>
        </div>

        <!--中间新闻-->
        <div class="col-xs-7">
            <div class="media">
                <div class="media-left">
                    <a href="news.html">
                        <img class="media-object news-png"
                             src="../static/img/index1.jpg"
                             alt="新闻图片"></a>
                </div>
                <div class="media-body">
                    <h4 class="media-heading"><b>2年前他为教育和高圆圆分手,今成这般,高圆圆:我有一句MMP如哽在喉</b></h4>
                    <div class="news-info">
                        <img class="news-logo" src="../static/img/u=1271327272,62771227&fm=26&gp=0.jpg">
                        <span>王花花</span>.
                        <span>25K评论</span>.
                        <span>7分钟前</span>
                    </div>
                </div>
            </div>
             <div class="media">
                <div class="media-left">
                    <a href="news.html">
                        <img class="media-object news-png"
                             src="../static/img/2.2.jpg"
                             alt="新闻图片"></a>
                </div>
                <div class="media-body">
                    <h4 class="media-heading"><b>2年前他为教育和高圆圆分手,今成这般,高圆圆:我有一句MMP如哽在喉</b></h4>
                    <div class="news-info">
                        <img class="news-logo" src="../static/img/u=1271327272,62771227&fm=26&gp=0.jpg">
                        <span>王花花</span>.
                        <span>25K评论</span>.
                        <span>7分钟前</span>
                    </div>
                </div>
            </div>

            </div>

                      <!--页角-->
            <nav aria-label="Page navigation">
                <ul class="pagination">
                    <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">上一页</span></a>
                    </li>
                    <li class="active"><a href="#">1 <span class="sr-only">(current)</span></a></li>
                    <li><a href="#">2 <span class="sr-only">(current)</span></a></li>
                    <li><a href="#">3 <span class="sr-only">(current)</span></a></li>
                    <li><a href="#">4 <span class="sr-only">(current)</span></a></li>
                    <li><a href="#">... <span class="sr-only">(current)</span></a></li>
                    <li><a href="#">10 <span class="sr-only">(current)</span></a></li>
                    <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">下一页</span></a>
                    </li>
                </ul>
            </nav>
        </div>

        <div class="col-xs-3">
                       <!--搜索栏-->
                <div class="input-group input-info">
                  <input type="text" class="form-control" placeholder="搜一下">
                </div>
                     <!--有害信息-->
                <div class="bad-infomation">
                    <table id="bad-table">
                        <tr>
                            <td rowspan="2">
                                <img class="bad-jpg" src="../static/img/4.png">
                            </td>
                            <td id="bad-font1">有害信息举报专区</td>
                        </tr>
                        <tr>
                            <td id="bad-font2">
                                举报电话12377
                            </td>
                        </tr>
                    </table>
                </div>

                    <!--新闻推荐-->
            <div class="list-group hot-news">
                <a href="#" class="list-group-item">
                    <span style="font-size: larger"><b>24小时热闻</b></span>
                </a>
                <a href="#" class="list-group-item"><span style="font-size: large"> Lorem ipsum dolor sit amet,consectetur adipisicing</span><div class="news-info">
                        <span>25K评论</span>
                        <span>7分钟前</span></div></a>
                <a href="#" class="list-group-item"><span style="font-size: large"> Lorem ipsum dolor sit amet,consectetur adipisicing</span><div class="news-info">
                        <span>25K评论</span>
                        <span>7分钟前</span></div></a>
                <a href="#" class="list-group-item"><span style="font-size: large"> Lorem ipsum dolor sit amet,consectetur adipisicing</span><div class="news-info">
                        <span>25K评论</span>
                        <span>7分钟前</span></div></a>
                <a href="#" class="list-group-item"><span style="font-size: large"> Lorem ipsum dolor sit amet,consectetur adipisicing</span><div class="news-info">
                        <span>25K评论</span>
                        <span>7分钟前</span></div></a>
                <a href="#" class="list-group-item"><span style="font-size: large"> Lorem ipsum dolor sit amet,consectetur adipisicing</span><div class="news-info">
                        <span>25K评论</span>
                        <span>7分钟前</span></div></a>

            </div>
        </div>
    </div>
</div>
{% endblock %}
login.html:
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}

{% block title %}
登陆
{% endblock %}
{% block newcontent %}
      <!--登陆界面-->
 <div class="container container-small login">
    <h1>登录
      <small>没有账号?<a href="/register/">注册</a></small>
    </h1>
     {{wtf.quick_form(form)}}
      {% if message %}
        <p style="color: red">{{message}}</p>
      {% endif %}
    <!--</form>-->
  </div>
{% endblock %}

在这里插入图片描述

在这里插入图片描述

signup.html:
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}

{% block title %}
注册
{% endblock %}
{% block newcontent %}
            <!--注册界面-->
<div class="container container-small login">
    <h1>注册
      <small>没有账号?<a href="/register/">注册</a></small>
    </h1>
    {{wtf.quick_form(form)}}
      <div class="form-group">
        注册咖啡或浮云即代表您同意<a href="#">咖啡或浮云服务条款</a>
      </div>
      {% if message %}
        <p style="color: red">{{message}}</p>
      {% endif %}

  </div>
{% endblock %}

在这里插入图片描述

在这里插入图片描述

sysinfo.html:
{% extends 'base.html' %}
{% block title %} 系统信息 {% endblock %}
{% block newcontent %}
{#    表格内容----bootstrap #}
<table class="table table-striped" style="width: 50%; margin: auto " >
    <tr>
        <td><b style="font-size: large">系统信息</b></td>
        <td></td>
    </tr>
    <tr>
        <td>主机名</td>
        <td>{{ hostname }}</td>
    </tr>
    <tr>
        <td>内核名称</td>
        <td>{{ sysname }}</td>
    </tr>
    <tr>
        <td>发行版本号</td>
        <td>{{ release }}</td>
    </tr>
    <tr>
        <td>内核版本</td>
        <td>{{ version}}</td>
    </tr>
    <tr>
        <td>系统构架</td>
        <td>{{ machine }}</td>
    </tr>
    <tr>
        <td>现在时间</td>
        <td>{{ now_time }}</td>
    </tr>
    <tr>
        <td>开机时间</td>
        <td>{{ boot_time }}</td>
    </tr>
    <tr>
        <td>运行时间</td>
        <td>{{ delta_time }}</td>
    </tr>
</table>

{% endblock %}

在这里插入图片描述

userinfo.html:
{% extends 'base.html' %}
{% import "bootstrap/wtf.html" as wtf %}

{% block title %} 用户信息 {% endblock %}
{% block newcontent %}
    <table class="table table-striped" style="width: 50%; margin: auto " >
        <tr>
            <td><b style="font-size: large">用户信息</b></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
         <tr>
                <th>编号</th>
                <th>用户名</th>
                <th>创建时间</th>
                <th>用户角色</th>
         </tr>
        {% for user in users %}
                <tr>
                    <td>{{ user.id }}</td>
                    <td>{{ user.name }}</td>
                    <td>{{ user.add_time }}</td>
                    {#  因为反向引用               #}
                    <td>{{ user.role.name }}</td>

                </tr>

        {% endfor %}
    </table>
{% endblock %}

在这里插入图片描述

404.html:
{% extends "bootstrap/base.html" %}
{% block content %}
<h2 style="color: red;">404: 页面未找到</h2>
{% endblock }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值