08_展示表指定的列

2018-11-07 大宝

1 效果图

用户管理界面中,展示的是数据库中的user表,只展示其中的三个列first_name、last_name、login

2 代码说明

manage.py代码中找到class MyModelView,修改为

class MyModelView(sqla.ModelView):

def is_accessible(self):
return login.current_user.is_authenticated
# 08_展示表指定的列
column_list = ('first_name','last_name','login')

Flask-admin 框架中对于ModelView的帮助链接Flask-admin官方帮助

3 操作指南

3.1 使用myweb用户登陆服务器

su - myweb
[root@am_01 ~]# su - myweb
Last login: Wed Nov 7 10:53:02 CST 2018 on pts/1
[myweb@am_01 ~]$ cd PonyTail/
[myweb@am_01 PonyTail]$ pwd
/home/myweb/PonyTail
[myweb@am_01 PonyTail]$ ll
total 12
-rw-rw-r--. 1 myweb myweb 1 Nov 2 18:33 __init__.py
-rw-rw-r--. 1 myweb myweb 6436 Nov 7 11:05 manage.py
drwxrwxr-x. 3 myweb myweb 98 Nov 5 16:42 templates

3.2 修改manage.py

代码中注释为“ # 08_展示数据库指定的列”的下一行就是新增的代码

修改后的manange.py文件如下:

# -*- coding:utf8 -*- 

from flask import Flask
from flask_admin import Admin
from flask_admin import BaseView
from flask_admin import expose
from flask_babelex import Babel
from flask_sqlalchemy import SQLAlchemy
from flask_admin.contrib.sqla import ModelView
# 07_新增登陆界面:加载模块
from flask import url_for, redirect, render_template, request
from wtforms import form, fields, validators
import flask_admin as admin
import flask_login as login
from flask_admin.contrib import sqla
from flask_admin import helpers
from werkzeug.security import generate_password_hash, check_password_hash



db = SQLAlchemy()
app = Flask(__name__)
babel = Babel(app)

#set optional bootswatch theme
#app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'
app.config['BABEL_DEFAULT_LOCALE'] = 'zh_CN'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:myweb@localhost:3306/myweb?charset=utf8'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 07_新增登陆界面:配置key才能使用session
# Create dummy secrey key so we can use sessions
app.config['SECRET_KEY'] = '123456790'


db.init_app(app)

# models
# Create user model.
# 07_新增登陆界面:将原来的UserAdmin表改为User
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(100))
last_name = db.Column(db.String(100))
login = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120))
password = db.Column(db.String(64))

# Flask-Login integration
# NOTE: is_authenticated, is_active, and is_anonymous
# are methods in Flask-Login < 0.3.0
@property
def is_authenticated(self):
return True

@property
def is_active(self):
return True

@property
def is_anonymous(self):
return False

def get_id(self):
return self.id

# Required for administrative interface
def __unicode__(self):
return self.username


# Define login and registration forms (for flask-login)
class LoginForm(form.Form):
login = fields.StringField(validators=[validators.required()])
password = fields.PasswordField(validators=[validators.required()])
#password = fields.StringField(validators=[validators.required()])

def validate_login(self, field):
user = self.get_user()

if user is None:
raise validators.ValidationError('Invalid user')

# we're comparing the plaintext pw with the the hash from the db
#if not check_password_hash(user.password, self.password.data):
# to compare plain text passwords use
if user.password != self.password.data:
raise validators.ValidationError('Invalid password')

def get_user(self):
return db.session.query(User).filter_by(login=self.login.data).first()


class RegistrationForm(form.Form):
login = fields.StringField(validators=[validators.required()])
email = fields.StringField()
password = fields.PasswordField(validators=[validators.required()])

def validate_login(self, field):
if db.session.query(User).filter_by(login=self.login.data).count() > 0:
raise validators.ValidationError('Duplicate username')


# Initialize flask-login
def init_login():
login_manager = login.LoginManager()
login_manager.init_app(app)

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


# Create customized model view class
class MyModelView(sqla.ModelView):

def is_accessible(self):
return login.current_user.is_authenticated
# 08_展示表指定的列
column_list = ('first_name','last_name','login')

# Create customized index view class that handles login & registration
class MyAdminIndexView(admin.AdminIndexView):

@expose('/')
def index(self):
if not login.current_user.is_authenticated:
return redirect(url_for('.login_view'))
return super(MyAdminIndexView, self).index()

@expose('/login/', methods=('GET', 'POST'))
def login_view(self):
# handle user login
form = LoginForm(request.form)
if helpers.validate_form_on_submit(form):
user = form.get_user()
login.login_user(user)

if login.current_user.is_authenticated:
return redirect(url_for('.index'))
link = '<p>Don\'t have an account? <a href="' + url_for('.register_view') + '">Click here to register.</a></p>'
self._template_args['form'] = form
self._template_args['link'] = link
return super(MyAdminIndexView, self).index()

@expose('/register/', methods=('GET', 'POST'))
def register_view(self):
form = RegistrationForm(request.form)
if helpers.validate_form_on_submit(form):
user = User()

form.populate_obj(user)
# we hash the users password to avoid saving it as plaintext in the db,
# remove to use plain text:
#user.password = generate_password_hash(form.password.data)

db.session.add(user)
db.session.commit()

login.login_user(user)
return redirect(url_for('.index'))
link = '<p>Already have an account? <a href="' + url_for('.login_view') + '">Click here to log in.</a></p>'
self._template_args['form'] = form
self._template_args['link'] = link
return super(MyAdminIndexView, self).index()

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






# Add administrative views here
class Happy(BaseView):
@expose('/')
def index(self):
return self.render('happy.html')

class Birthday(BaseView):
@expose('/')
def index(self):
return self.render('birthday.html')



# Flask views
@app.route('/')
def index():
return render_template('index.html')


# Initialize flask-login
init_login()

admin = Admin(app, name='PonyTail', index_view=MyAdminIndexView(), base_template='my_master.html', template_mode='bootstrap3')
admin.add_view(Happy(name=u'工作之愉'))
admin.add_view(Birthday(name=u'年年有今日岁岁有今朝'))
admin.add_view(MyModelView(User,db.session,name=u'用户管理'))

if __name__ == "__main__":
app.run(debug=True,host='0.0.0.0',port=5000)

3.7 运行程序

[myweb@am_01 PonyTail]$ python manage.py 
* Serving Flask app "manage" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 476-676-292

访问网站http://10.200.6.150:5000/

4 拓展练习

4.1 实现列名映射和排序功能

阅读Flask-admin官方帮助 实现以下功能:

  • 展示user表的列名从First_name、Last_name、Login改为名、性、用户名

  • 展示user表时,可以通过login列进行排序

效果图如下:

答案:

将类MyModelView的代码进行添加:

class MyModelView(sqla.ModelView):

def is_accessible(self):
return login.current_user.is_authenticated
# 08_展示表指定的列
column_list = ('first_name','last_name','login')
# 08_展示表映射列名
column_labels = {
'first_name':u'名',
'last_name':u'姓',
'login':u'用户名'
}
# 08_展示表可排序的列
column_sortable_list = ('login',)

4.2 实现表的明细查看

当前我们的user表只展示了三个列,要求通过点击某个按钮可以查看所有列的信息。效果图如下:

红色框框中多了一个眼睛的图形,点击后,进入下图的“详情”:

答案:

class MyModelView(sqla.ModelView):

def is_accessible(self):
return login.current_user.is_authenticated
# 08_展示表指定的列
column_list = ('first_name','last_name','login')
# 08_展示表映射列名
column_labels = {
'first_name':u'名',
'last_name':u'姓',
'login':u'用户名'
}
# 08_展示表可排序的列
column_sortable_list = ('login',)
# 08_展示表详情
can_view_details = True

5 manage.py的代码

# -*- coding:utf8 -*- 

from flask import Flask
from flask_admin import Admin
from flask_admin import BaseView
from flask_admin import expose
from flask_babelex import Babel
from flask_sqlalchemy import SQLAlchemy
from flask_admin.contrib.sqla import ModelView
# 07_新增登陆界面:加载模块
from flask import url_for, redirect, render_template, request
from wtforms import form, fields, validators
import flask_admin as admin
import flask_login as login
from flask_admin.contrib import sqla
from flask_admin import helpers
from werkzeug.security import generate_password_hash, check_password_hash



db = SQLAlchemy()
app = Flask(__name__)
babel = Babel(app)

#set optional bootswatch theme
#app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'
app.config['BABEL_DEFAULT_LOCALE'] = 'zh_CN'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:myweb@localhost:3306/myweb?charset=utf8'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 07_新增登陆界面:配置key才能使用session
# Create dummy secrey key so we can use sessions
app.config['SECRET_KEY'] = '123456790'


db.init_app(app)

# models
# Create user model.
# 07_新增登陆界面:将原来的UserAdmin表改为User
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(100))
last_name = db.Column(db.String(100))
login = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120))
password = db.Column(db.String(64))

# Flask-Login integration
# NOTE: is_authenticated, is_active, and is_anonymous
# are methods in Flask-Login < 0.3.0
@property
def is_authenticated(self):
return True

@property
def is_active(self):
return True

@property
def is_anonymous(self):
return False

def get_id(self):
return self.id

# Required for administrative interface
def __unicode__(self):
return self.username


# Define login and registration forms (for flask-login)
class LoginForm(form.Form):
login = fields.StringField(validators=[validators.required()])
password = fields.PasswordField(validators=[validators.required()])
#password = fields.StringField(validators=[validators.required()])

def validate_login(self, field):
user = self.get_user()

if user is None:
raise validators.ValidationError('Invalid user')

# we're comparing the plaintext pw with the the hash from the db
#if not check_password_hash(user.password, self.password.data):
# to compare plain text passwords use
if user.password != self.password.data:
raise validators.ValidationError('Invalid password')

def get_user(self):
return db.session.query(User).filter_by(login=self.login.data).first()


class RegistrationForm(form.Form):
login = fields.StringField(validators=[validators.required()])
email = fields.StringField()
password = fields.PasswordField(validators=[validators.required()])

def validate_login(self, field):
if db.session.query(User).filter_by(login=self.login.data).count() > 0:
raise validators.ValidationError('Duplicate username')


# Initialize flask-login
def init_login():
login_manager = login.LoginManager()
login_manager.init_app(app)

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


# Create customized model view class
class MyModelView(sqla.ModelView):

def is_accessible(self):
return login.current_user.is_authenticated
# 08_展示表指定的列
column_list = ('first_name','last_name','login')
# 08_展示表映射列名
column_labels = {
'first_name':u'名',
'last_name':u'姓',
'login':u'用户名'
}
# 08_展示表可排序的列
column_sortable_list = ('login',)
# 08_展示表详情
can_view_details = True

# Create customized index view class that handles login & registration
class MyAdminIndexView(admin.AdminIndexView):

@expose('/')
def index(self):
if not login.current_user.is_authenticated:
return redirect(url_for('.login_view'))
return super(MyAdminIndexView, self).index()

@expose('/login/', methods=('GET', 'POST'))
def login_view(self):
# handle user login
form = LoginForm(request.form)
if helpers.validate_form_on_submit(form):
user = form.get_user()
login.login_user(user)

if login.current_user.is_authenticated:
return redirect(url_for('.index'))
link = '<p>Don\'t have an account? <a href="' + url_for('.register_view') + '">Click here to register.</a></p>'
self._template_args['form'] = form
self._template_args['link'] = link
return super(MyAdminIndexView, self).index()

@expose('/register/', methods=('GET', 'POST'))
def register_view(self):
form = RegistrationForm(request.form)
if helpers.validate_form_on_submit(form):
user = User()

form.populate_obj(user)
# we hash the users password to avoid saving it as plaintext in the db,
# remove to use plain text:
#user.password = generate_password_hash(form.password.data)

db.session.add(user)
db.session.commit()

login.login_user(user)
return redirect(url_for('.index'))
link = '<p>Already have an account? <a href="' + url_for('.login_view') + '">Click here to log in.</a></p>'
self._template_args['form'] = form
self._template_args['link'] = link
return super(MyAdminIndexView, self).index()

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






# Add administrative views here
class Happy(BaseView):
@expose('/')
def index(self):
return self.render('happy.html')

class Birthday(BaseView):
@expose('/')
def index(self):
return self.render('birthday.html')



# Flask views
@app.route('/')
def index():
return render_template('index.html')


# Initialize flask-login
init_login()

admin = Admin(app, name='PonyTail', index_view=MyAdminIndexView(), base_template='my_master.html', template_mode='bootstrap3')
admin.add_view(Happy(name=u'工作之愉'))
admin.add_view(Birthday(name=u'年年有今日岁岁有今朝'))
admin.add_view(MyModelView(User,db.session,name=u'用户管理'))

if __name__ == "__main__":
app.run(debug=True,host='0.0.0.0',port=5000)