a本期目标:模板创建
1、安装wtforms
pip install wtforms
2、模板
templates\cms\cms_login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial=1">
<!-- 前面三个meta标签必须放在最前面! -->
<title>凤凰论坛 - CMS登录</title>
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link href="{{ url_for('static', filename='cms/css/signin.css') }}" rel="stylesheet">
</head>
<body>
<div class="top-pannel">
<h2>凤凰论坛</h2>
<br>
<p>fhuang forum</p>
</div>
<div class="content">
<form class="form-signin">
<br><br><br><br><br><br><br><br><br><br><br>
<h2 class="from-sign-heading">请登录:</h2>
<label for="inputEmail" class="sr-only">邮箱:</label>
<input type="email" id="inputEmail"class="form-control" placeholder="邮箱" required autofocus>
<label for="inputPassword" class="sr-only">密码:</label>
<input type="password" id="inputPassword" class="form-control" placeholder="密码" required>
<div class="checkbox">
<label>
<input type="checkbox" value="remember-me">记住我
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">立即登录</button>
</form>
</div>
</body>
</html>
static\cms\css\signin.css
body {
padding-top: 40px;
padding-bottom: 40px;
background-color: #eee;
}
.form-signin {
max-width: 330px;
padding: 15px;
margin: 0 auto;
}
.form-signin .form-signin-heading,
.form-signin .checkbox {
margin-bottom: 10px;
}
.form-signin .checkbox {
font-weight: normal;
}
.form-signin .form-control {
position: relative;
height: auto;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 10px;
font-size: 16px;
}
.form-signin .form-control:focus {
z-index: 2;
}
.form-signin input[type="email"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.top-pannel {
background-color: #444;
height: 120px;
width: 100%;
text-align: center;
border-radius: 8px;
color: #eee;
position: fixed;
top: 0;
}
.content {
top: 25%;
}
apps\cms\views.py
from flask import Blueprint, views, render_template
cms_blueprint = Blueprint("cms", __name__, url_prefix="/cms")
@cms_blueprint.route("/")
def index():
return "fhuang forum's cms"
class LoginView(views.MethodView):
def get(self):
return render_template("cms/cms_login.html")
def post(self):
pass
cms_blueprint.add_url_rule("/login/", view_func=LoginView.as_view("login"))
运行fhuang_forum.py,访问http://127.0.0.1/cms/login/
?ohhhhhhhhhhhhh~
3、后台登录功能
修改templates\cms\cms_login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial=1">
<!-- 前面三个meta标签必须放在最前面! -->
<title>凤凰论坛 - CMS登录</title>
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link href="{{ url_for('static', filename='cms/css/signin.css') }}" rel="stylesheet">
</head>
<body>
<div class="top-pannel">
<h2>凤凰论坛</h2>
<br>
<p>fhuang forum</p>
</div>
<div class="content">
<form class="form-signin">
<br><br><br><br><br><br><br><br><br><br><br>
<h2 class="form-signin-heading">请登录</h2>
<label for="inputEmail" class="sr-only">邮箱:</label>
<input type="email" id="inputEmail" class="form-control" name="email" placeholder="邮箱" required autofocus>
<label for="inputPassword" class="sr-only">密吗</label>
<input type="password" id="inputPassword" class="form-control" name="password" placeholder="密码" required>
<div class="checkbox">
<label>
<input type="checkbox" value="1" name="remember"> 记住我
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">立即登录</button>
</form>
{% if message %}
<p style="text-align: center" class="text-danger">{{ message }}</p>
{% endif %}
</div>
</body>
</html>
在apps\cms\里新建forms.py
from wtforms import Form, StringField, IntegerField
from wtforms.validators import Email, InputRequired, Length
class LoginForm(Form):
email = StringField(validators=[Email(message="请输入正确的邮箱格式"), InputRequired(message="请输入邮箱")])
password = StringField(validators=[Length(6, 20, message="密码长度不够或超出")])
remember = IntegerField()
?apps\cms\views.py
from flask import Blueprint, views, render_template, request, session, url_for, redirect
from .forms import LoginForm
from .models import CMSUser
cms_blueprint = Blueprint("cms", __name__, url_prefix="/cms")
@cms_blueprint.route("/")
def index():
return "fhuang forum's cms"
class LoginView(views.MethodView):
def get(self, message=None):
return render_template("cms/cms_login.html", message=message)
def post(self):
form = LoginForm(request.form)
if form.validate():
email = form.email.data
password = form.password.data
remember = form.remember.data
user = CMSUser.query.filter_by(email=email).first()
if user and user.check_password(password):
session["user_id"] = user.id
if remember:
session.permanent = True
return redirect(url_for("cms.index"))
else:
return self.get(message="用户名或密码错误")
else:
message = form.errors.popitem()[1][0]
return self.get(message=message)
cms_blueprint.add_url_rule("/login/", view_func=LoginView.as_view("login"))
修改config.py
import os
SECRET_KEY = os.urandom(24)
CMS_USER_ID = "abcdefg"
DEBUG = True
SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:123456@127.0.0.1:3306/bbs?charset=utf8"
SQLALCHEMY_TRACK_MODIFICATIONS = False
修改apps\cms\views.py
from flask import Blueprint, views, render_template, request, session, url_for, redirect
from .forms import LoginForm
from .models import CMSUser
cms_blueprint = Blueprint("cms", __name__, url_prefix="/cms")
@cms_blueprint.route("/")
def index():
return "fhuang forum's cms"
class LoginView(views.MethodView):
def get(self, message=None):
return render_template("cms/cms_login.html", message=message)
def post(self):
form = LoginForm(request.form)
if form.validate():
email = form.email.data
password = form.password.data
remember = form.remember.data
user = CMSUser.query.filter_by(email=email).first()
if user and user.check_password(password):
session[config.CMS_USER_ID] = user.id
if remember:
session.permanent = True
return redirect(url_for("cms.index"))
else:
return self.get(message="用户名或密码错误")
else:
message = form.errors.popitem()[1][0]
return self.get(message=message)
cms_blueprint.add_url_rule("/login/", view_func=LoginView.as_view("login"))
在apps\cms\里新建decorators.py
from flask import session, redirect, url_for
from functools import wraps
import config
def login_required(func):
@wraps(func)
def inner(*args, **kwargs):
if config.CMS_USER_ID in session:
return func(*args, **kwargs)
else:
return redirect(url_for("cms.login"))
return inner
修改:apps\cms\views.py
from flask import Blueprint, views, render_template, request, session, url_for, redirect
from .forms import LoginForm
from .models import CMSUser
from .decorators import login_required
cms_blueprint = Blueprint("cms", __name__, url_prefix="/cms")
@cms_blueprint.route("/")
@login_required
def index():
return "fhuang forum's cms"
class LoginView(views.MethodView):
def get(self, message=None):
return render_template("cms/cms_login.html", message=message)
def post(self):
form = LoginForm(request.form)
if form.validate():
email = form.email.data
password = form.password.data
remember = form.remember.data
user = CMSUser.query.filter_by(email=email).first()
if user and user.check_password(password):
session[config.CMS_USER_ID] = user.id
if remember:
session.permanent = True
return redirect(url_for("cms.index"))
else:
return self.get(message="用户名或密码错误")
else:
message = form.errors.popitem()[1][0]
return self.get(message=message)
cms_blueprint.add_url_rule("/login/", view_func=LoginView.as_view("login"))
4、后台模板
在templates\里新建文件夹common
在templates\common\里新建_macros.html
{% macro static(filename) %}
{{ url_for("static", filename=filename) }}
{%- endmacro %}
在templates\cms\里新建cms_index.html
修改apps\cms\views.py
from flask import Blueprint, views, render_template, request, session, url_for, redirect
from .forms import LoginForm
from .models import CMSUser
from .decorators import login_required
cms_blueprint = Blueprint("cms", __name__, url_prefix="/cms")
@cms_blueprint.route("/")
@login_required
def index():
return render_template("cms/cms_index.html")
class LoginView(views.MethodView):
def get(self, message=None):
return render_template("cms/cms_login.html", message=message)
def post(self):
form = LoginForm(request.form)
if form.validate():
email = form.email.data
password = form.password.data
remember = form.remember.data
user = CMSUser.query.filter_by(email=email).first()
if user and user.check_password(password):
session[config.CMS_USER_ID] = user.id
if remember:
session.permanent = True
return redirect(url_for("cms.index"))
else:
return self.get(message="用户名或密码错误")
else:
message = form.errors.popitem()[1][0]
return self.get(message=message)
cms_blueprint.add_url_rule("/login/", view_func=LoginView.as_view("login"))
在templates\cms\里新建cms_index.html
?
{% from "common/_macros.html" import static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>凤凰论坛 - CMS</title>
<link rel="stylesheet" href="{{ static('cms/css/signin.css') }}">
<link rel="stylesheet" href="https://cdn.staticfile.org/foundation/5.5.3/css/foundation.min.css">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/foundation/5.5.3/js/foundation.min.js"></script>
<script src="https://cdn.staticfile.org/foundation/5.5.3/js/vendor/modernizr.js"></script>
</head>
<body>
<div class="top-pannel">
<h2 style="color:#eee">凤凰论坛 - hzh论坛管理后台</h2>
<br>
<p>fhuang forum</p>
</div>
<br><br><br><br><br><br>
<div class="row" style="float:left;">
<div class="medium-4 columns" style="background-color: #444;">
<ul class="side-nav">
<li class="active"><a href="#">首页</a></li>
<li><a href="#">个人中心</a></li>
<li><a href="#"> 个人信息</a></li>
<li><a href="#"> 修改密码</a></li>
<li><a href="#"> 修改邮箱</a></li>
<li><a href="#">帖子管理</a></li>
<li><a href="#">评论管理</a></li>
<li><a href="#">板块管理</a></li>
<li><a href="#">用户管理</a></li>
<li><a href="#">CMS用户管理</a></li>
<li><a href="#">CMS组管理</a></li>
</ul>
</div>
<div class="medium-8 columns">
<h1>我的论坛</h1>
</div>
</div>
</body>
</html>
?
大概是这样子的:?
|