2.1.cms后台登录界面完成 (1)templates/cms/cms_login.html
< ! DOCTYPE html>
< html lang= "zh-CN" >
< head>
< meta charset= "utf-8" >
< meta http- equiv= "X-UA-Compatible" content= "IE=edge" >
< meta name= "viewport" content= "width=device-width, initial-scale=1" >
< ! -- 上述3 个meta标签* 必须* 放在最前面,任何其他内容都* 必须* 跟随其后! -- >
< meta name= "description" content= "" >
< meta name= "author" content= "" >
< title> CMS 登录界面< / title>
< ! -- Bootstrap core CSS -- >
< link href= "https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel= "stylesheet" >
< ! -- Custom styles for this template -- >
< link href= "{{ url_for('static',filename='cms/css/signin.css') }}" rel= "stylesheet" >
< / head>
< body>
< div class = "container" >
< form class = "form-signin" >
< h2 class = "form-signin-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> < ! -- / container -- >
< / body>
< / html>
(2)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 ;
}
(3)cms/views.py
# cmd/ views. py
__author__ = 'derek'
from flask import Blueprint, views, render_template
bp = Blueprint ( "cms" , __name__, url_prefix= '/cms' )
@bp. route ( '/' )
def index ( ) :
return 'cms index'
class LoginView ( views. MethodView) :
def get ( self) :
return render_template ( 'cms/cms_login.html' )
def post ( self) :
pass
bp. add_url_rule ( '/login/' , view_func= LoginView. as_view ( 'login' ) )
浏览器访问:http://127.0.0.1:5000/cms/login/
2.2.cms后台登录功能完成 (1)cms/cms_login.html
< form class = "form-signin" method= "post" >
< 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 % }
(2)cms/forms.py
# cmd/ 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 ( )
(4)cms/views.py
# cmd/ views. py
__author__ = 'derek'
from flask import Blueprint, views, render_template, request, session
from flask import url_for, redirect
from . forms import LoginForm
from . models import CMSUser
bp = Blueprint ( "cms" , __name__, url_prefix= '/cms' )
@bp. route ( '/' )
def index ( ) :
return 'cms index'
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 :
# 31 天后过期
session. permanent = True
return redirect ( url_for ( 'cms.index' ) )
else :
return self. get ( message= '用户名或密码错误' )
else :
#form. errors的错误信息格式,是一个字典,value是列表的形式
# { 'email' : [ '请输入正确的邮箱格式' ] , 'password' : [ '密码长度不够或超出' ] }
message = form. errors. popitem ( ) [ 1 ] [ 0 ]
return self. get ( message= message)
bp. add_url_rule ( '/login/' , view_func= LoginView. as_view ( 'login' ) )
(4)config.py
import os
SECRET_KEY = os. urandom ( 24 )
2.3.cms后台登录限制 (1)config.py
CMS_USER_ID = 'abcdefg' #随便写一值,这样session更加安全
(2)修改LoginView
session[ config. CMS_USER_ID ] = user. id
(3)cms/decorators.py
# 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
(4)cms/cms_login.py
@bp. route ( '/' )
@login_required
def index ( ) :
return 'cms index'
2.4.cms后台模板渲染完成 (1)static/cms/css/base.css
body {
padding- top: 50px;
overflow : hidden;
}
. sub- header {
padding- bottom: 10px;
border- bottom: 1px solid #eee;
}
. navbar- fixed- top {
border : 0 ;
}
. sidebar {
display : none;
}
@media ( min- width: 768px ) {
. sidebar {
position : fixed;
top : 51px;
bottom : 0 ;
left : 0 ;
z- index: 1000 ;
display : block;
padding : 20px;
overflow- x: hidden;
overflow- y: auto;
background- color: #363a47;
border- right: 1px solid #eee;
margin- top: - 1px;
}
}
. nav- sidebar{
padding : 5px 0 ;
margin- left: - 20px;
margin- right: - 20px;
}
. nav- sidebar > li{
background : #494f60;
border- bottom: 1px solid #363a47;
border- top: 1px solid #666 ;
line- height: 35px;
}
. nav- sidebar > li > a {
background : #494f60;
color : #9b9fb1;
margin- left: 25px;
display : block;
}
. nav- sidebar > li a span{
float : right;
width : 10px;
height : 10px;
border- style: solid;
border- color: #9b9fb1 #9b9fb1 transparent transparent;
border- width: 1px;
transform : rotate ( 45deg) ;
position : relative;
top : 10px;
margin- right: 10px;
}
. nav- sidebar > li > a: hover{
color : #fff;
background : #494f60;
text- decoration: none;
}
. nav- sidebar > li > . subnav{
display : none;
}
. nav- sidebar > li. unfold{
background : #494f60;
}
. nav- sidebar > li. unfold > . subnav{
display : block;
}
. nav- sidebar > li. unfold > a{
color : #db4055;
}
. nav- sidebar > li. unfold > a span{
transform : rotate ( 135deg) ;
top : 5px;
border- color: #db4055 #db4055 transparent transparent;
}
. subnav{
padding- left: 10px;
padding- right: 10px;
background : #363a47;
overflow : hidden;
}
. subnav li{
overflow : hidden;
margin- top: 10px;
line- height: 25px;
height : 25px;
}
. subnav li. active{
background : #db4055;
}
. subnav li a{
color : #9b9fb1;
padding- left: 30px;
height : 25px;
line- height: 25px;
}
. subnav li a: hover{
color : #fff;
}
. nav- group{
margin- top: 10px;
}
. main {
padding : 20px;
}
@media ( min- width: 768px ) {
. main {
padding- right: 40px;
padding- left: 40px;
}
}
. main . page- header {
margin- top: 0 ;
}
. placeholders {
margin- bottom: 30px;
text- align: center;
}
. placeholders h4 {
margin- bottom: 0 ;
}
. placeholder {
margin- bottom: 20px;
}
. placeholder img {
display : inline- block;
border- radius: 50 % ;
}
. main_content{
margin- top: 20px;
}
. top- group{
padding : 5px 10px;
border- radius: 2px;
background : #ecedf0;
overflow : hidden;
}
. top- box{
overflow : hidden;
background : #ecedf0;
padding : 10px 5px;
}
(2)static/cms/js/base.js
$ ( function ( ) {
$ ( '.nav-sidebar>li>a' ) . click ( function ( event ) {
var that = $ ( this ) ;
if ( that. children ( 'a' ) . attr ( 'href' ) == '#' ) {
event. preventDefault ( ) ;
}
if ( that. parent ( ) . hasClass ( 'unfold' ) ) {
that. parent ( ) . removeClass ( 'unfold' ) ;
} else {
that. parent ( ) . addClass ( 'unfold' ) . siblings ( ) . removeClass ( 'unfold' ) ;
}
console. log ( 'coming....' ) ;
} ) ;
$ ( '.nav-sidebar a' ) . mouseleave ( function ( ) {
$ ( this ) . css ( 'text-decoration' , 'none' ) ;
} ) ;
} ) ;
$ ( function ( ) {
var url = window. location. href;
if ( url. indexOf ( 'profile' ) >= 0 ) {
var profileLi = $ ( '.profile-li' ) ;
profileLi. addClass ( 'unfold' ) . siblings ( ) . removeClass ( 'unfold' ) ;
profileLi. children ( '.subnav' ) . children ( ) . eq ( 0 ) . addClass ( 'active' ) . siblings ( ) . removeClass ( 'active' ) ;
} else if ( url. indexOf ( 'resetpwd' ) >= 0 ) {
var profileLi = $ ( '.profile-li' ) ;
profileLi. addClass ( 'unfold' ) . siblings ( ) . removeClass ( 'unfold' ) ;
profileLi. children ( '.subnav' ) . children ( ) . eq ( 1 ) . addClass ( 'active' ) . siblings ( ) . removeClass ( 'active' ) ;
} else if ( url. indexOf ( 'resetemail' ) >= 0 ) {
var profileLi = $ ( '.profile-li' ) ;
profileLi. addClass ( 'unfold' ) . siblings ( ) . removeClass ( 'unfold' ) ;
profileLi. children ( '.subnav' ) . children ( ) . eq ( 2 ) . addClass ( 'active' ) . siblings ( ) . removeClass ( 'active' ) ;
} else if ( url. indexOf ( 'posts' ) >= 0 ) {
var postManageLi = $ ( '.post-manage' ) ;
console. log ( postManageLi) ;
postManageLi. addClass ( 'unfold' ) . siblings ( ) . removeClass ( 'unfold' ) ;
} else if ( url. indexOf ( 'boards' ) >= 0 ) {
var boardManageLi = $ ( '.board-manage' ) ;
boardManageLi. addClass ( 'unfold' ) . siblings ( ) . removeClass ( 'unfold' ) ;
} else if ( url. indexOf ( 'permissions' ) >= 0 ) {
var permissionManageLi = $ ( '.permission-manage' ) ;
permissionManageLi. addClass ( 'unfold' ) . siblings ( ) . removeClass ( 'unfold' ) ;
} else if ( url. indexOf ( 'fusers' ) >= 0 ) {
var userManageLi = $ ( '.user-manage' ) ;
userManageLi. addClass ( 'unfold' ) . siblings ( ) . removeClass ( 'unfold' ) ;
} else if ( url. indexOf ( 'cusers' ) >= 0 ) {
var cmsuserManageLi = $ ( '.cmsuser-manage' ) ;
cmsuserManageLi. addClass ( 'unfold' ) . siblings ( ) . removeClass ( 'unfold' ) ;
} else if ( url. indexOf ( 'croles' ) >= 0 ) {
var cmsroleManageLi = $ ( '.cmsrole-manage' ) ;
cmsroleManageLi. addClass ( 'unfold' ) . siblings ( ) . removeClass ( 'unfold' ) ;
} else if ( url. indexOf ( 'comments' ) >= 0 ) {
var commentsManageLi = $ ( '.comments-manage' ) ;
commentsManageLi. addClass ( 'unfold' ) . siblings ( ) . removeClass ( 'unfold' ) ;
} else if ( url. indexOf ( 'banners' ) >= 0 ) {
var bannerManageLi= $ ( '.banner-manage' ) ;
bannerManageLi. addClass ( 'unfold' ) . siblings ( ) . removeClass ( 'unfold' ) ;
}
} ) ;
(3)templates/common/_macros.html
创建一个宏
{ #“- ”表示去掉换行#}
{ % macro static ( filename) - % }
{ { url_for ( "static" , filename= filename) } }
{ % - endmacro % }
(4)templates/cms/cms_index.html
{ % from "common/_macros.html" import static % }
< ! DOCTYPE html>
< html lang= "en" >
< head>
< meta charset= "UTF-8" >
< title> 标题< / title>
< script src= "http://cdn.bootcss.com/jquery/3.1.1/jquery.min.js" > < / script>
< link href= "http://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel= "stylesheet" >
< script src= "http://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js" > < / script>
< link rel= "stylesheet" href= "{{ static('cms/css/base.css') }}" >
< script src= "{{ static('cms/js/base.js')}}" > < / script>
< / head>
< body>
< nav class = "navbar navbar-inverse navbar-fixed-top" role= "navigation" >
< div class = "container-fluid" >
< div class = "navbar-header" >
< button type= "button" class = "navbar-toggle collapsed" data- toggle= "collapse" data- target= "#navbar" aria- expanded= "false" aria- controls= "navbar" >
< 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= "#" > Zhang_derek论坛管理后台< / a>
< / div>
< div id= "navbar" class = "navbar-collapse collapse" >
< ul class = "nav navbar-nav navbar-right" >
< li> < a href= "#" > derek< span> [ 超级管理员] < / span> < / a> < / li>
< li> < a href= "#" > 注销< / a> < / li>
< / ul>
< form class = "navbar-form navbar-right" >
< input type= "text" class = "form-control" placeholder= "查找..." >
< / form>
< / div>
< / div>
< / nav>
< div class = "container-fluid" >
< div class = "row" >
< div class = "col-sm-3 col-md-2 sidebar" >
< ul class = "nav-sidebar" >
< li class = "unfold" > < a href= "#" > 首页< / a> < / li>
< li class = "profile-li" >
< a href= "#" > 个人中心< span> < / span> < / a>
< ul class = "subnav" >
< li> < a href= "#" > 个人信息< / a> < / li>
< li> < a href= "#" > 修改密码< / a> < / li>
< li> < a href= "#" > 修改邮箱< / a> < / li>
< / ul>
< / li>
< li class = "nav-group post-manage" > < a href= "#" > 帖子管理< / a> < / li>
< li class = "comments-manage" > < a href= "#" > 评论管理< / a> < / li>
< li class = "board-manage" > < a href= "#" > 板块管理< / a> < / li>
< li class = "nav-group user-manage" > < a href= "#" > 用户管理< / a> < / li>
< li class = "nav-group cmsuser-manage" > < a href= "#" > CMS 用户管理< / a> < / li>
< li class = "cmsrole-manage" > < a href= "#" > CMS 组管理< / a> < / li>
< / ul>
< / div>
< div class = "col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main" >
< h1> 我的论坛< / h1>
< / div>
< / div>
< / div>
< / body>
< / html>
(5)app/cms/views.py
@bp. route ( '/' )
@login_required
def index ( ) :
return render_template ( 'cms/cms_index.html' )
访问:http://127.0.0.1:5000/cms/
本文由LIKE.TG编辑部转载自互联网并编辑,如有侵权影响,请联系官方客服 ,将为您妥善处理。
This article is republished from public internet and edited by the LIKE.TG editorial department. If there is any infringement, please contact our official customer service for proper handling.