电影订票系统后台开发(3)管理系统

电影订票系统后台开发(3)管理系统
完整项目请戳 猿眼电影订票系统

Let’s go

项目开发环境

  • Deepin-Linux 15.4
  • Python 2.7.12
  • PyCharm
  • Flask

管理系统

前面我们已经讲到了数据模型,成功使用 ORM 建了项目所需的数据库表,现在我们要考虑一个问题,我们要怎么管理数据库中的数据呢,比如一个电影订票系统,肯定会有电影的信息和上映的场次信息,如果我们要添加这些信息,每次都用数据库可视化软件直接操作数据库的话非常麻烦,效率也不高,这个时候我们就需要一个后台管理系统,登录该系统后可以对数据库中的数据进行增删改查。
猿眼电影订票管理系统效果如下,完整项目请戳 猿眼电影订票系统

管理系统登录界面

电影管理界面

电影数据修改界面

实现上面的效果只需要简单的几步

安装

Flask-Admin是一个功能齐全、简单易用的Flask扩展,可以为 Flask 应用程序增加管理界面,很方便地实现一个后台管理系统,Flask-Admin 快速入门

1
2
(venv) $ pip install Flask-Admin        # 安装 Flask-Admin
(venv) $ pip freeze > requiremens.txt # 更新需求文件

初始化

1
2
3
4
5
6
7
8
from flask import Flask
from flask_admin import Admin

app = Flask(__name__)
admin = Admin(app, name=u'猿眼管理系统') # 等价于下面两句
# admin = Admin(name=u'猿眼管理系统')
# admin.init_app(app)
app.run()

运行之后访问 http://localhost:5000/admin/ 就可以看到一个简单的管理界面。

增加视图

作为后台管理系统,当然需要添加登录界面,保证管理系统的安全性,用Flask-Login做身份验证,Flask-WTF防止跨站请求伪造攻击(CSRF)。
Flask-Login 官方文档
Flask-WTF 快速入门

1
2
(venv) $ pip install Flask-Login Flask-WTF  # 安装 Flask-Login Flask-WTF
(venv) $ pip freeze > requiremens.txt # 更新需求文件

新建一个views.py文件,添加一个登录表单的类,其中的 User 类就是数据模型中的用户表,此时 User 类还需要继承 flask_login 中的UserMixin类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from models import User
from flask_wtf import FlaskForm
from wtforms import fields, validators, ValidationError

class LoginForm(FlaskForm):
"""登录表单"""
username = fields.StringField(validators=[validators.data_required()])
password = fields.PasswordField(validators=[validators.data_required()])

def validate_username(self, field):
"""登录校验"""
user = self.get_user()

if user is None:
raise ValidationError('Invalid user')
if self.password.data != user.password:
raise ValidationError('Invalid password')

def get_user(self):
return User.query.filter_by(id=self.username.data, isAdmin=1).first()

有了登录表单之后,增加一个视图,如果未登录就重定向到登录界面,已登录就显示管理系统首页,这里需要在templates文件夹中添加模板文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import flask_login as login
from flask_login import login_required
from flask_admin import expose, AdminIndexView, helpers

class MyAdminIndexView(AdminIndexView):
@expose('/')
def index(self):
if not isAdmin():
return redirect(url_for('.login_view'))
return super(MyAdminIndexView, self).index()

@expose('/login/', methods=('GET', 'POST'))
def login_view(self):
form = LoginForm(request.form)

if helpers.validate_form_on_submit(form):
user = form.get_user()
login.login_user(user)

if isAdmin():
return redirect(url_for('.index'))

self._template_args['form'] = form
return super(MyAdminIndexView, self).index()

@expose('/logout/')
@login_required
def logout_view(self):
login.logout_user()
return redirect(url_for('.login_view'))

数据库模型视图

模型视图允许你为数据库中的每个模型增加专用的管理页面。比如现在要为电影模型单独添加一个管理页面,只需新建一个继承ModelView的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from wtforms import fields
from flask_admin.contrib.sqla import ModelView

class MovieModelView(ModelView):
column_exclude_list = ('description',) # 不显示的字段
# 表单字段
form_columns = ('expired', 'name', 'poster', 'description',
'playingTime', 'duration', 'movieType', 'playingType')
form_create_rules = form_columns[1:] # 新建时显示的字段
form_overrides = {'poster': fields.FileField} # 重写表单类型

# 自定义字段显示
form_args = {
'movieType': {
'render_kw': {
'placeholder': '电影类型, 中文逗号分隔'
}
}
}

# 当模型的数据改变时触发(新建或修改)
def on_model_change(self, form, movie, is_created):
# do something
pass

然后初始化登录,添加模型视图即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# -*- coding: utf-8 -*-
from views import *
import flask_login as login
from flask_admin import Admin
from models import db, Movie, User

def init_login(app):
"""初始化登录"""
login_manager = login.LoginManager()
login_manager.init_app(app)

# Create user loader function
@login_manager.user_loader
def load_user(id):
return User.query.get(id)

admin = Admin(name='猿眼管理系统', template_mode='bootstrap3',
index_view=MyAdminIndexView(), base_template='admin.html')
movieModelView = MovieModelView(Movie, db.session, name='电影管理')
admin.add_view(movieModelView)

注意 管理系统需要用到管理员账号和密码,上次我们是在代码中设置了数据库的ip端口以及账号密码,这是很不安全的,当你把代码提交到 github 上时这些私密配置也会被别人知道,Flask 中可以在instance文件夹中进行私密配置,提交到 github 上时只需要在.gitignore中忽略该文件夹即可。

1
2
app = Flask(__name__, instance_relative_config=True)
app.config.from_pyfile('config.py') # 加载私密配置 instance/config.py

项目目录结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
├── MonkeyEye-Server
│   ├── app
│   │   ├── admin
│   │   │   ├── __init__.py
│   │   │   ├── admin.py
│   │   │   └── views.py
│   │   ├── __init__.py
│   │   ├── models.py
│   │   ├── static
│   │   │   ├── css
│   │   │   ├── images
│   │   │   └── js
│   │   └── templates
│   │      ├── admin
│ │      │   └── index.html
│   │      └── admin.html
│   ├── instance
│   │   ├── config.py
│   │   └── __init__.py
│   └── server.py
├── README.md
├── requirements
└── venv/

参考链接

文章目录
  1. Let’s go
    1. 项目开发环境
    2. 管理系统
      1. 安装
      2. 初始化
      3. 增加视图
      4. 数据库模型视图
  2. 参考链接
|
-->