python操作三大主流数据库(6)python操作mysql⑥新闻管理后台功能的完善(增、ajax异步删除新闻、改、查)
python操作mysql⑥新闻管理后台功能的完善(增、删、改、查)
安装表单验证
D:\python\python_mysql_redis_mongodb\version02>pip install Flask-WTF
表单验证功能
http://flask.pocoo.org/docs/0.11/patterns/wtforms/
目录结构:
[root@node1 mysql_version03]# tree -L 3 . ├── flask_news.py ├── forms.py ├── static │ ├── bootstrap-3.3.7-dist │ │ ├── css │ │ ├── fonts │ │ └── js │ ├── bootstrap-3.3.7-dist.zip │ ├── datatables.min.css │ ├── datatables.min.js │ ├── img │ │ └── news │ ├── index.css │ ├── jquery-3.3.1.min.js │ └── main.css └── templates ├── admin │ ├── add.html │ ├── admin_base.html │ ├── index.html │ └── update.html ├── cat.html ├── detail.html ├── home_base.html └── index.html
1.服务端功能代码flask_news.py
# coding:utf-8 from flask import Flask, flash from datetime import datetime from flask_sqlalchemy import SQLAlchemy from flask import render_template, redirect from forms import NewsForm app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:@localhost:3306/news?charset=utf8' app.config['SECRET_KEY'] = 'adfa@4314#31AD23#2' db = SQLAlchemy(app) class News(db.Model): __tablename__ = 'news' id = db.Column(db.Integer, primary_key = True) title = db.Column(db.String(200), nullable = False) content = db.Column(db.String(2000), nullable = False) types = db.Column(db.String(10), nullable = False) image = db.Column(db.String(1300), ) author = db.Column(db.String(20), ) view_count = db.Column(db.Integer) created_at = db.Column(db.DateTime) is_valid = db.Column(db.Boolean) @app.route('/hello') def hello_world(): return 'hello flask' ''' 创建news_test数据库 建表 cmd下输入Python,导入包,使用命令生成表,并进行简单的操作 >>> from flask_news import db >>> from flask_news import News >>> news01 = News(title= 'title01',content='content01',types='baijia') >>> db.session.add(news01) >>> db.session.commit() ''' @app.route('/') def index(): '''新闻首页''' news_list = News.query.all() print(news_list) return render_template('index.html', news_list = news_list) @app.route('/index/') def index_html(): '''新闻首页''' new_list = News.query.all() return redirect('/') @app.route('/cat/<name>/') def cat(name): '''新闻的类别''' # 查询 news_list = News.query.filter(News.types == name) return render_template('cat.html', name = name, news_list = news_list) @app.route('/detail/<int:pk>/') def detail(pk): '''新闻详情信息''' obj = News.query.get(pk) return render_template('detail.html', obj = obj) @app.route('/admin/') @app.route('/admin/<int:page>/') def admin(page=None): '''后台新闻列表''' if page is None: page = 1 news_list = News.query.filter_by(is_valid=True).paginate(page = page, per_page = 3) # print (news_list.items) return render_template('admin/index.html', news_list = news_list) @app.route('/admin/update/<int:pk>/', methods = ['GET', 'POST']) def admin_update(pk): '''后台新闻列表''' new_obj = News.query.get(pk) print('admin_update:new_obj %s' % new_obj) if not new_obj: return redirect(url_for('admin')) form = NewsForm(obj = new_obj) if form.validate_on_submit(): new_obj.title = form.title.data new_obj.content = form.content.data new_obj.types = form.types.data new_obj.created_at = datetime.now() # 保存数据 db.session.add(new_obj) db.session.commit() # 文字提示flash消息闪现 flash('修改成功') return redirect('/admin/') return render_template('admin/update.html', new_obj = new_obj,form = form) @app.route('/admin/add/') def admin_add(): '''跳转到后台新闻列表''' # 将form对象传入add.html页面 # 参考 http://flask-wtf.readthedocs.io/en/latest/quickstart.html#creating-forms form = NewsForm() return render_template('admin/add.html',form = form) @app.route('/admin/do_add/', methods = ['POST']) def admin_do_add(): ''' 新增新闻信息 ''' form = NewsForm() if form.validate_on_submit(): # 获取数据 new_obj = News( title = form.title.data, content = form.content.data, types = form.types.data, image = form.image.data, created_at = datetime.now() ) # 保存数据 print(new_obj) db.session.add(new_obj) db.session.commit() # 文字提示flash消息闪现 flash('添加成功') return redirect('/admin/') @app.route('/admin/delete/<int:pk>/', methods = ['GET','POST']) def admin_delete(pk): ''' 删除新闻信息 ''' new_obj = News.query.get(pk) if not new_obj: return 'no' new_obj.is_valid = 0 db.session.add(new_obj) db.session.commit() return 'yes' if __name__ == "__main__": app.run(debug = True)
2.表单功能forms.py
from flask_wtf import FlaskForm from wtforms import StringField, TextAreaField, SubmitField, SelectField from wtforms.validators import DataRequired class NewsForm(FlaskForm): """新闻表单数据验证""" title = StringField(label = '新闻标题', validators = [DataRequired('请输入标题')], description = '请输入标题', render_kw={'required':'required', 'class':'form-control'}) content = TextAreaField(label = '新闻内容', validators = [DataRequired('请输入新闻内容')], description = '请输入新闻内容', render_kw={'required':'required', 'class':'form-control'}) types = SelectField('新闻类型', choices = [('推荐','推荐'), ('百家', '百家'),('本地','本地'), ('图片','图片')]) image = StringField(label='新闻图片', description='请输入图片地址', render_kw={'required':'required', 'class':'form-control'}) submit = SubmitField('提交')
3.后台模板代码
①模板代码admin_base.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='bootstrap-3.3.7-dist/css/bootstrap.min.css')}}"> {% block head %} <title>首页</title> {% endblock %} </head> <body> <!-- 导航栏 --> <div class="container"> <div class="row"> <div class="bs-example" data-example-id="default-navbar"> <nav class="navbar navbar-default"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <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="{{ url_for('admin_add')}}">添加新闻</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li> <li><a href="#">Link</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> <li role="separator" class="divider"></li> <li><a href="#">One more separated link</a></li> </ul> </li> </ul> <form class="navbar-form navbar-left"> <div class="form-group"> <input type="text" class="form-control" placeholder="Search"> </div> <button type="submit" class="btn btn-default">Submit</button> </form> <ul class="nav navbar-nav navbar-right"> <li><a href="#">Link</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> </ul> </li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> <!-- 新闻内容部分 --> {% block content %} <!-- 内容区域 --> {% endblock %} </div> {% block extrajs %} <!-- 其他脚本 --> {% endblock %} </body> </html>
②首页index.html
{% extends 'admin/admin_base.html' %} {% block head %} <title>新闻后台首页</title> {% endblock %} {% block content %} <!-- 消息闪现 --> {% for msg in get_flashed_messages() %} <p class="bg-success">{{msg}}</p> {% endfor %} <!-- 表格,存放新闻具体内容 --> <table class="table table-hover"> <tr class="info"> <th>编号</th> <th>新闻标题</th> <th>类别</th> <th>添加时间</th> <th>操作</th> </tr> {% for new_obj in news_list.items %} <tr class="active"> <td>{{ new_obj.id }}</td> <td>{{ new_obj.title }}</td> <td>{{new_obj.types }}</td> <td>{{new_obj.created_at }}</td> <td><a href='/admin/update/{{ new_obj.id }}/' class='btn btn-success'>修改</a><a data-url='{{ url_for('admin_delete', pk=new_obj.id) }}' href="javascript:;" class='btn btn-danger'>删除</a></td> </tr> {% endfor %} </table> <!-- 分页,默认分页 --> <nav aria-label="Page navigation"> <ul class="pagination"> <!-- {% macro pagination_news_list(news_list, adaamin) %} --> <li> {% if news_list.has_prev %} <a href="#" aria-label="Previous"> <span aria-hidden="true">«</span> </a> {% else %} {% endif %} </li> {% for page in news_list.iter_pages() %} <li> <a href="{{ url_for('admin', page=page) }}">{{ page }}</a> </li> {% endfor %} <li> {% if news_list.has_next %} <a href="#" aria-label="Next"> <span aria-hidden="true">»</span> </a> {% endif %} </li> </ul> <!-- {% endmacro %} --> </nav> </div> </div> {% endblock %} {% block extrajs %} <script type="text/javascript"> // 通过ajax异步删除新闻 $(function(){ $('.btn-danger').on('click', function(){ var _this = $(this); var url = _this.attr('data-url'); // 确认是否删除 if(confirm('确认删除吗?')){ // ajax调用 $.post(url, function(res){ //处理结果 if(res == 'yes'){ _this.parents('tr').hide() }else{ alert('删除失败') } }) } }) }) </script> {% endblock %} </body> </html>
③添加新闻add.html
{% extends 'admin/admin_base.html' %} {% block head %} <title>新闻添加页面</title> {% endblock %} {% block content %} <!-- 添加新闻内容 --> <form action="/admin/do_add/" method="post"> <div class="form-group"> <label for="exampleInputEmail1">{{ form.title.label.text }}</label> <input type="text" name="title" class="form-control" id="exampleInputEmail1" placeholder="news title"> </div> <div class="form-group"> <label for="exampleInputPassword1">{{ form.types.label.text }}</label> <div> {{ form.types }} </div> </div> <div class="form-group"> <label for="exampleInputFile">{{ form.image.label.text }}</label> <input type="file" name="image" id="exampleInputFile"> <p class="help-block">新闻图片上传</p> </div> <div class="form-group"> {{ form.content }} </div> <br> {{ form.csrf_token }} {{ form.submit }} </form> {% endblock %} </body> </html>
④修改新闻update.html
{% extends 'admin/admin_base.html' %} {% block head %} <title>修改新闻</title> {% endblock %} {% block content %} <form role='form' class="form-horizontal" method="post"> <div class="form-group"> <label for="exampleInputEmail1">{{ form.title.label.text }}</label> <div> {{form.title}} </div> </div> <div class="form-group"> <label for="exampleInputPassword1">{{ form.types.label.text }}</label> <div> {{ form.types }} </div> </div> <div class="form-group"> <label for="exampleInputFile">{{ form.image.label.text }}</label> <input type="file" name="image" id="exampleInputFile"> <!-- <p class="help-block">新闻图片上传</p> --> </div> <div class="form-group"> {{ form.content }} </div> <br> {{ form.csrf_token }} {{ form.submit }} </form> {% endblock %} </body> </html>