初步flask运行
写下程序blog.py并运行
from flask import Flask
app=Flask(__name__)
@app.route('/')#使用装饰器装饰根目录
def index():
return 'Blog for me'
在项目(blog.py)所在文件夹中打开cmd,设置如下:
cd C:\Users\Pondsi\Desktop\HARD_LEARN\develop_flask\FLASK_START
set FLASK_APP=blog.py
set FLASK_ENV=development
并输入以下指令开始运行
flask run
如果确认是development环境且debug mode on,修改blog.py的index return内容时 如果刷新网页改变对应内容,则至此成功
样式导入
在blog.py所在文件夹建立templates文件夹,放入对应html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sharing blog</title>
</head>
<body>
<header>
<h1>欢迎访问Sharing Blogs</h1>
<nav>
<!-- 这里可以放导航链接 -->
</nav>
</header>
<main>
<p>你可以在此分享你的一切</p>
</main>
<footer>
Sharing Blogs
<!-- 页脚内容 -->
</footer>
</body>
</html>
修改blog.py,import render_templates,并返回对应html
在html的head中加入link
<link rel="stylesheet" href="{{url_for('static',filename='css/style.css')}}">
在static的css中编写对应h1样式
h1{
border:auto #eee solid;
color: brown;
text-align: center;
padding: auto;
}
使用bootsrap样式
下载bootstrap内容放入static的css和js中 往templates中加入base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
<link rel="stylesheet" href="{{url_for('static',filename='css/bootstrap.min.css')}}">
<title>{%block title %}{%endblock%}</title>
</head>
<body>
<nav class="navbar navbar-expand-md navbar-light bg-light">
<a class="navbar-brand" href="{{url_for('index')}}">
Sharing Blogs
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="#">关于sharing</a>
</li>
</ul>
</div>
</nav>
<div class="container">
{% block content %}{% endblock %}
</div>
<script src="{{url_for('static',filename='js/jquery.slim.min.js')}}"></script>
<script src="{{url_for('static',filename='js/proper.min.js')}}"></script>
<script src="{{url_for('static',filename='js/bootstrap.min.js')}}"></script>
</body>
</html>
此时,便可直接根据控制字块调用以及修改博客内容
{% extends 'base.html' %}
{% block content %}
I am a student.
{% endblock %}
使用sqlite3构造数据库
创建db.sql进行表形态定义
DROP TABLE IF EXISTS posts;
CREATE TABLE posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
title TEXT NOT NULL,
content TEXT NOT NULL
);
初始化数据库,并尝试链接数据库获取句柄并插入数据
import sqlite3
conn=sqlite3.connect('database.db')
with open('db.sql') as f:
conn.executescript(f.read())
#创建执行句柄,用以执行语句
cur=conn.cursor()
cur.execute("INSERT INTO posts(title,content) VALUES (?,?)",
('学习Flask1','Sharing your flask part 1'))
cur.execute("INSERT INTO posts(title,content) VALUES (?,?)",
('学习Flask2','Sharing your flask part 2'))
conn.commit()
conn.close()
更改blog.py,加入数据库读取部分,将数据库内容装入index.html
from flask import Flask,render_template
import sqlite3
app=Flask(__name__)
def get_db_conn():
conn=sqlite3.connect('database.db')
conn.row_factory=sqlite3.Row
return conn
@app.route('/')#使用装饰器装饰根目录
def index():
conn= get_db_conn()
posts=conn.execute('select * from posts').fetchall()
return render_template('index.html',posts=posts)
展示文章列表
修改index.html,在标题下加入博客遍历,并加入创建时间戳与底部横线美化
{% extends 'base.html' %}
{% block content %}
<h1>欢迎访问Sharing Blogs</h1>
{% for post in posts %}
<a href="{{ url_for('post', id=post['id']) }}">
<h2>{{ post['title'] }}</h2>
</a>
<span class="badge badge-primary">{{post['created']}}</span>
<hr>
{% endfor %}
{% endblock %}
新建文章表单
在templates文件夹中新建new.html,在blog.py加入对应函数
// ... existing code ...
@app.route('/posts/new',methods=['GET','POST'])
def new():
return render_template('new.html')
// ... existing code ...
构建new.html内容如下
{% extends 'base.html' %}
{% block content %}
<h1>{%block title %}New Blog{% endblock %}</h1>
<form method="post">
<div class="form-group">
<label for="title">标题</label>
<input type="text" class="form-control" id="title" name="title" value="{{ request.form.title }}">
</div>
<div class="form-group">
<label for="content">内容</label>
<textarea class="form-control" placeholder="博客内容" name="content">{{ request.form['content'] }}</textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">提交</button>
</div>
</form>
{% endblock %}
文件详情页
在templates文件夹中新建post.html,在blog.py加入对应函数
// ... existing code ...
def get_post(post_id):
conn=get_db_conn()
post=conn.execute('select * from posts where id=?',(post_id,)).fetchone()
conn.close()
return post
// ... existing code ...
@app.route('/posts/<int:post_id>')
def post(post_id):
post=get_post(post_id)
return render_template('post.html',post=post)
// ... existing code ...
构建post.html内容如下,为美观加入时间戳
{% extends 'base.html' %}
{% block content %}
<h1>{% block title %}{{post['title']}}{%endblock%}</h1>
<span class="badge badge-primary">{{post['created']}}</span>
<p>{{post['content']}}</p>
{% endblock %}
新建博客并保存
在templates文件夹中修改new.html,修改blog.py:导入request、urlfor、flash、redirt,并在new()中加入对应功能,实现若为POST请求将请求体内容插入数据库中提交并重定向新Blog,加入网站密钥
from flask import Flask,render_template,request,url_for,flash,redirect
// ... existing code ...
app.config['SECRET_KEY'] ='sharing your flask,love is key'
// ... existing code ...
@app.route('/posts/new',methods=['GET','POST'])
def new():
if request.method=='POST':
title=request.form['title']
content=request.form['content']
if not title:
flash('标题不可为空')
elif not content:
flash('内容不可为空')
else:
conn=get_db_conn()
conn.execute('insert into posts(title,content) values (?,?)',(title,content))
conn.commit()
conn.close()
flash('成功提交Blog')
return redirect(url_for('index'))
return render_template('new.html')
// ... existing code ...
##增加新建文章提示 在base.html的容器中加入遍历message提示flash的控制块
{% for message in get_flashed_messages() %}
<div class="alert alert-danger">{{message}}</div>
{% endfor %}
修改index的展示逻辑,变为order by created的按创造时间排序
// ... existing code ...
posts=conn.execute('select * from posts order by created DESC').fetchall()
// ... existing code ...
修改base,在指定列表中加入新建Blog链接
<li class="nav-item active">
<a class="nav-link" href="{{url_for('new')}}">新建Blog</a>
</li>
编辑博客
在blog.py中加入编辑函数edit
@app.route('/posts/<int:post_id>/edit',methods=['GET','POST'])
def edit(post_id):
post=get_post(post_id)
if request.method=='POST':
title=request.form['title']
content=request.form['content']
if not title:
flash('标题不可为空')
elif not content:
flash('内容不可为空')
else:
conn=get_db_conn()
conn.execute('update posts set title=?,content=? where id=?',(title,content,post_id))
conn.commit()
conn.close()
flash('成功修改Blog')
return redirect(url_for('index'))
return render_template('edit.html',post=post)
在templates文件夹中新建edit.html,注意:编辑中的标题内容可能来自于post或request
{% extends 'base.html' %}
{% block content %}
<h1>{% block title %}编辑"{{post['title']}}"{% endblock %}</h1>
<form method="post">
<div class="form-group">
<label for="title">标题</label>
<input type="text" class="form-control" id="title" name="title"
value="{{ request.form['title'] or post['title'] }}">
<!-- 这里尤其注意 -->
</div>
<div class="form-group">
<label for="content">内容</label>
<textarea class="form-control" placeholder="博客内容"
name="content">{{ request.form['内容'] or post['content'] }}</textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">提交</button>
</div>
</form>
<hr>
{% endblock %}
删除博客
在blog.py中加入删除函数delete,注意使用POST方法而不用GET方法,防止爬虫删除数据
@app.route('/posts/<int:post_id>/delete',methods=['POST'])
def delete(post_id):
post=get_post(post_id)
conn=get_db_conn()
conn.execute('delete from posts where id=?',(post_id,))
conn.commit()
conn.close()
flash('成功删除Blog"{}"'.format(post['title']))
return redirect(url_for('index'))
修改post.html,加入删除按钮
<form action="{{ url_for('delete', id=post['id']) }}" method="POST">
<input type="submit" value="删除" class="btn btn-danger btn-sm"
onclick="return confirm('确定要删除吗?')">
</form>