Flask 快速搭建模板1
- 快速搭建基础框架
成品预览
pip安装
需要导入的基础包
pip install flask
pip install flask-sqlalchemy
pip install flask-wtf
pip install bootstrap-flask
pip install flask-login
pip install flask-moment
创建目录结构
type nul > main.py
type nul > config.py
type nul > models.py
type nul > forms.py
type nul > run.bat
md templates
md static
type nul > templates\base.html
run.bat
点击查看代码
root_path=%~dp0
echo current dir: %root_path%
cd %root_path%
call %root_path%.venv\Scripts\activate.bat
python main.py
pause
main.py
点击查看代码
import datetime
from flask import Flask, flash, redirect, render_template, url_for, request
from werkzeug.security import generate_password_hash, check_password_hash
from flask_sqlalchemy import SQLAlchemy
from flask_bootstrap import Bootstrap4
from flask_login import LoginManager, current_user, login_user, logout_user, UserMixin,login_required
from flask_moment import Moment
from config import Config
# 创建app 实例
app = Flask(__name__)
app.config.from_object(Config)
# 定义扩展插件
db = SQLAlchemy(app)
bootstrap = Bootstrap4(app)
login_manager = LoginManager(app)
moment = Moment(app)
# 初始化
# db.init_app(app)
# bootstrap.init_app(app)
# login_manager.init_app(app)
login_manager.login_view = 'login'
# moment.init_app(app)
# 数据库定义
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(30))
password_hash = db.Column(db.String(128))
create_time = db.Column(db.DateTime)
status = db.Column(db.String(10))
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
@login_manager.user_loader
def load_user(userid):
return User.query.get(userid)
# 路由
@app.route('/', methods=['GET', 'POST'])
@app.route('/index', methods=['GET', 'POST'])
def index():
return render_template('index.html')
@app.route('/view')
@login_required
def view():
return render_template('view.html')
# 注册
@app.route('/register', methods=['GET', 'POST'])
def register():
if current_user.is_authenticated:
return redirect(url_for('index'))
from forms import RegisterForm
form = RegisterForm()
if form.validate_on_submit():
username = form.username.data
password = form.password.data
if User.query.filter_by(username=username).first():
flash("用户已存在")
return redirect(url_for('register'))
user = User(username=username, create_time=datetime.datetime.now())
user.set_password(password)
db.session.add(user)
db.session.commit()
flash("创建用户成功,请登录后使用")
return redirect(url_for('login'))
return render_template('register.html', form=form)
# 登录
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('index'))
from forms import LoginForm
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is None or not user.check_password(form.password.data):
flash('无效的用户或者密码')
return redirect(url_for('login'))
login_user(user, remember=form.remember_me.data)
next_page = request.args.get('next')
# if not next_page or url_parse(next_page).netloc != '':
if not next_page:
next_page = url_for('index')
return redirect(next_page)
return render_template('login.html', title="登录", form=form)
@app.route('/logout')
def logout():
logout_user()
return redirect(url_for('index'))
if __name__ == '__main__':
# # 初始化数据库
# with app.app_context():
# db.create_all()
app.run(host='127.0.0.1', debug=True, port=1234)
config.py
点击查看代码
import os
import sys
# SQLite URI compatible
WIN = sys.platform.startswith('win')
if WIN:
prefix = 'sqlite:///'
else:
prefix = 'sqlite:////'
basedir = os.path.abspath(os.path.dirname(__file__))
class Config:
SECRET_KEY = "1234567890"
SQLALCHEMY_DATABASE_URI = prefix + os.path.join(basedir, 'data.db')
print(f"ttt: {SQLALCHEMY_DATABASE_URI}")
SQLALCHEMY_TRACK_MODIFICATIONS = False
BOOTSTRAP_SERVE_LOCAL = True
forms.py
点击查看代码
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, PasswordField, BooleanField
from wtforms.validators import DataRequired, Length, EqualTo
from wtforms import ValidationError
class RegisterForm(FlaskForm):
username = StringField('用户名', validators=[DataRequired(), Length(1, 30)])
password = PasswordField('密码', validators=[DataRequired()])
re_password = PasswordField('再次输入密码',
validators=[DataRequired(), EqualTo('password', message="两次输入的密码不一致")])
submit = SubmitField("注册")
# def validate_username(self, username):
# from main import User
# user = User.query.filter_by(username=username.data).first()
# if user is not None:
# raise ValidationError('用户已存在')
class LoginForm(FlaskForm):
username = StringField('用户名', validators=[DataRequired(), Length(1, 30)])
password = PasswordField('密码', validators=[DataRequired(), Length(1, 30)])
remember_me = BooleanField('记住我')
submit = SubmitField("登录")
base.html
点击查看代码
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<meta charset="UTF-8">
<title>Title</title>
{% block css %}
{{ bootstrap.load_css() }}
<link rel="stylesheet" href="{{ url_for('static', filename='base.css') }}">
{% endblock css %}
{% endblock head %}
</head>
<body>
{% block body %}
{% if request.endpoint not in ['login','register'] %}
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="{{ url_for('index') }}">MyTools</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="{{ url_for('index') }}">首页 <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">特性一</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-expanded="false">
特性二
</a>
<div class="dropdown-menu">
<a class="dropdown-item" href="#">子特性一</a>
<a class="dropdown-item" href="#">子特性二</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">子特性三</a>
</div>
</li>
<li class="nav-item">
<a class="nav-link disabled">特性三</a>
</li>
</ul>
<div class="text-center">
{% if current_user.is_anonymous %}
<a href="{{ url_for('register') }}">注册</a>
{% else %}
<h4 class="text-light"><strong>Hi, {{ current_user.username }}</strong></h4>
{% endif %}
</div>
<div>
<span> </span>
</div>
<div>
{% if current_user.is_anonymous %}
<a href="{{ url_for('login') }}">登录</a>
{% else %}
<a href="{{ url_for('logout') }}">退出</a>
{% endif %}
</div>
</div>
</nav>
{% endif %}
<div class="container">
<div class="row justify-content-end">
{% for message in get_flashed_messages() %}
<div class="alert alert-danger alert-dismissible fade show col-5 float-right" role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endfor %}
</div>
<main>
{% block main %}
{% endblock main %}
</main>
</div>
<footer>
{% block footer %}
{% endblock footer %}
</footer>
{% block scripts %}
{{ bootstrap.load_js() }}
<script>
$('.alert1').alert('close')
</script>
{% endblock scripts %}
{% endblock body %}
</body>
</html>
index.html
点击查看代码
{% extends 'base.html' %}
{% block main %}
<h1 class="h3 mb-3 font-weight-normal">Index</h1>
{% endblock main%}
register.html
点击查看代码
{% extends 'base.html' %}
{% from "bootstrap/form.html" import render_form %}
{% block css %}
{{ super() }}
<link rel="stylesheet" href="{{ url_for('static', filename='login.css') }}">
{% endblock css %}
{% block main %}
<div>
<div class="row justify-content-center">
<div class="col-4">
<h1 class="h3 mb-3 font-weight-normal">用户注册</h1>
{{ render_form(form, action=request.full_path,horizontal_columns=('lg', 2, 4)) }}
</div>
</div>
</div>
{% endblock main%}
login.html
点击查看代码
{% extends 'base.html' %}
{% block css %}
{{ super() }}
<link rel="stylesheet" href="{{ url_for('static', filename='login.css') }}">
{% endblock css %}
{% block main %}
<form class="form-signin" method="post">
<h1 class="h3 mb-3 font-weight-normal">欢迎使用,请登录</h1>
<h6 class="h6 mb-3 font-weight-normal">没有账户,请<a href="{{ url_for('register') }}">注册</a></h6>
{{ form.csrf_token }}
{{ form.username.label(class="sr-only") }}
{{ form.username(class="form-control", placeholder="用户名",required="required",autofocus="autofocus") }}
{% for message in form.username.errors %}
<small class="error">{{ message }}</small><br>
{% endfor %}
{{ form.password.label(class="sr-only") }}
{{ form.password(class="form-control",placeholder="密码",required="required") }}
{% for message in form.password.errors %}
<small class="error">{{ message }}</small><br>
{% endfor %}
<div class="checkbox mb-3">
<label>
{{ form.remember_me }} {{ form.remember_me.label }}
</label>
</div>
{{ form.submit(class="btn btn-lg btn-primary btn-block") }}
</form>
{% endblock main%}