python 操作三大主流数据库 第五课
tags:
- python3
- 慕课网
categories:
- python3
- mysql
- SQLAlchemy
- 网易新闻实战
文章目录
第一节 flask入门
1. 安装包
1. pip install -i https://pypi.douban.com/simple/ flask
2. pip install -i https://pypi.douban.com/simple/ Flask-SQLAlchemy
3. 帮助文档
- 英文文档: http://flask.pocoo.org/docs/0.11/
- 中文文档: http://docs.jinkan.org/docs/flask/
- Flask-SQL Alchemy:http://flask-sqlalchemy.pocoo.org/2.1/
2. Flask 第一个小程序
# -- coding: utf-8 --
from flask import Flask
app = Flask(__name__) # 构造出一个app对象
@app.route('/') # 通过app路由 装饰器 用户访问到指定地址
def hello_world(): # 然后把这个地址定义到一个方法中进行处理就好了。
return 'Hello World !'
"""
flask 里面有一个微小的服务器,供我们调试使用。
但是部署到服务器上不会用这个做,我们会用其他方式来做。
因为它的并发,负载可定是不够的,只能满足开发的需求!
"""
if __name__ == '__main__':
app.run(debug = True) # 用debug调试方式打开 按 cmd+s 保存的时候,服务器会自动重新启动。 将app运行起来。
第二节 搭建网易新闻框架
1. 项目介绍:
1. static 存放静态文件 JS JQuery CSS的图片
2. templates 用来放模板文件
3. 官方文档:https://docs.sqlalchemy.org/en/latest/core/tutorial.html
4. flask_new.py flask程序,里面调用forms表单
5. forms.py forms表单
6. bootstrap官网:http://v3.bootcss.com/css/
7. Utf8 字符 Utf8mb4 中文字符+微信表情 utf8mb4_general_ci
8. flask官方文档:https://flask.palletsprojects.com/en/1.1.x/
# -- coding: utf-8 --
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
"""
# 创建表 直接导入db对象
# from yourappliation import db
# db.create_all()
# flask_news 表的编码Utf8mb4 中文字符+微信表情 utf8mb4_general_ci
"""
app = Flask(__name__) # 构造出一个app对象
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123456@127.0.0.1/flask_news?charset=utf8'
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.Enum('推荐', '百家', '本地', '图片'))
image = db.Column(db.String(200), nullable=False)
author = db.Column(db.String(20))
view_count = db.Column(db.Integer)
created_at = db.Column(db.DateTime)
is_valid = db.Column(db.Boolean, default=True)
# print class对象的时候返回的是数据(新闻标题)、而不是地址。
def __repr__(self):
return '<News %r>' % self.title
if __name__ == '__main__':
app.run(debug=True)
第三节 新闻前台
1. 前台页面
1. 导入已经写好的静态文件
2. 导入数据库表格
3. github资源地址:git@github.com:QnHyn/flask_news.git
@app.route('/')
def index():
'''新闻首页'''
news_list = News.query.all()
return render_template('index.html', news_list=news_list)
@app.route('/cat/<name>/')
def cat(name):
'''新闻的类别'''
news_list = News.query.filter(News.types == name)
return render_template('index.html',name=name, news_list=news_list)
@app.route('/detail/<int:pk>/')
def detail(pk):
""" 新闻详情页 """
new_obj = News.query.get(pk)
return render_template('detail.html', new_obj=new_obj)
2. 后台管理以及分页功能
# 后台逻辑
@app.route('/admin/')
@app.route('/admin/<int:page>/')
def admin(page=None):
""" 新闻管理首页 """
if page is None:
page = 1
page_data = News.query.paginate(page=page, per_page=3)
return render_template('admin/index.html', page_data=page_data)
# 前台bootstrap
# 这里的has_prev、iter_pages、has_next都是page_data对象中封装好的
<nav>
<ul class="pagination">
{% if page_data.has_prev %}
<li><a href="{{ url_for('admin', page=page_data.prev_num) }}">«</a></li>
{% else %}
<li class="disabled"><a href="javscript:;">»</a></li>
{% endif %}
{% for page in page_data.iter_pages() %}
{% if page == page_data.page %}
<li class="active"><a href="javscript:;">{{ page }}</a></li>
{% else %}
<li><a href="{{ url_for('admin', page=page) }}">{{ page}}</a></li>
{% endif %}
{% endfor %}
{% if page_data.has_next %}
<li><a href="{{ url_for('admin', page=page_data.next_num ) }}">»</a></li>
{% else %}
<li class="disabled"><a href="javscript:;">»</a></li>
{% endif %}
</ul>
</nav>
3. 后台管理及新闻数据的新增
1. 表单Flask-WTF
2. pip install -i https://pypi.douban.com/simple/ Flask-WTF
from flask import Flask, render_template, flash, redirect, url_for
@app.route('/admin/add/', methods=('GET', 'POST'))
def add():
form = NewsForm()
if form.validate_on_submit():
# 获取数据
new_obj = News(
title=form.title.data,
content=form.content.data,
image=form.image.data,
types=form.types.data,
created_at=datetime.now(),
)
# 保存数据
db.session.add(new_obj)
db.session.commit()
flash("新增成功")
return redirect(url_for('admin'))
return render_template("admin/add.html", form=form)
# 表单 forms.py 内容
from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SubmitField, SelectField, RadioField
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=[('推荐', '推荐'), ('百家', '百家'), ('本地', '本地'), ('图片', '图片')],
render_kw={'class': 'form-control'})
image = StringField(label='新闻图片',
description='请输入图片地址',
render_kw={'class': 'form-control'})
submit = SubmitField('提交')
4. 后台管理及新闻数据的修改和异步删除
1. Ajax异步删除
2. 这次后台词用逻辑删除
def update(pk):
""" 修改新闻 """
obj = News.query.get(pk)
if obj is None:
abort(404)
form = NewsForm(obj=obj)
if form.validate_on_submit():
obj.title = form.title.data
obj.content = form.content.data
obj.news_type = form.types.data
db.session.add(obj)
db.session.commit()
flash("修改成功")
return redirect(url_for('admin'))
return render_template("admin/update.html", form=form)
@app.route('/admin/delete/<int:pk>/', methods=['POST'])
def delete(pk):
""" 异步ajax删除 逻辑删除 """
if request.method == 'POST':
obj = News.query.get(pk)
if obj is None:
return 'no'
obj.is_valid = False
db.session.add(obj)
db.session.commit()
return 'yes'
return 'no'
# 前台jquery Ajax异步删除
<script>
$(function(){
$('.btn-danger').on('click', function(){
var btn = $(this);
if(confirm('确定删除该记录吗?')){
$.post(btn.attr('data-url'), function(data){
if (data === 'yes'){
btn.parents('tr').hide();
}else{
alert('删除失败');
}
})
}
})
})
</script>