- 快速搭建基础框架
成品预览
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.pypause
main.py
点击查看代码
import datetimefrom 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 RegisterFormform = RegisterForm()if form.validate_on_submit():username = form.username.datapassword = form.password.dataif 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 LoginFormform = 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 = FalseBOOTSTRAP_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 ValidationErrorclass 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%}
[代码下载](https://files.cnblogs.com/files/tzyuan123/simple_flask.rar?t=1722755727&download=true "代码下载")