Ubuntu 16.04+Python 3.5.2+Vim
一、环境搭建
/usr/ccdocs
下新建一个目录【myproject
】,并将其更改为一个Python项目的文件夹,启动Pipenv:
chenchen@chenchen-ubuntu:~$ cd /usr/ccdocs
chenchen@chenchen-ubuntu:/usr/ccdocs$ sudo mkdir myproject
chenchen@chenchen-ubuntu:/usr/ccdocs$ sudo chmod 777 myproject
chenchen@chenchen-ubuntu:/usr/ccdocs$ cd myproject
chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ pipenv --three
Creating a virtualenv for this project…
Pipfile: /usr/ccdocs/myproject/Pipfile
Using /usr/bin/python3.5 (3.5.2) to create virtualenv…
⠼Running virtualenv with interpreter /usr/bin/python3.5
Using base prefix '/usr'
New python executable in /home/chenchen/.local/share/virtualenvs/myproject-f5Hwi5Rz/bin/python3.5
Also creating executable in /home/chenchen/.local/share/virtualenvs/myproject-f5Hwi5Rz/bin/python
Installing setuptools, pip, wheel...
done.
Virtualenv location: /home/chenchen/.local/share/virtualenvs/myproject-f5Hwi5Rz
Creating a Pipfile for this project…
chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ ll
总用量 12
drwxrwxrwx 2 root root 4096 11月 14 16:49 ./
drwxr-xr-x 4 root root 4096 11月 14 15:58 ../
-rw-rw-r-- 1 chenchen chenchen 138 11月 14 16:49 Pipfile
chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ pipenv lock
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (a79791)!
chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ ll
总用量 16
drwxrwxrwx 2 root root 4096 11月 14 17:16 ./
drwxr-xr-x 4 root root 4096 11月 14 15:58 ../
-rw-rw-r-- 1 chenchen chenchen 138 11月 14 16:49 Pipfile
-rw-r--r-- 1 chenchen chenchen 453 11月 14 17:16 Pipfile.lock
chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ pipenv shell
Launching subshell in virtual environment…
chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ . /home/chenchen/.local/share/virtualenvs/myproject-f5Hwi5Rz/bin/activate
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$
安装Flask:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ pipenv install flask
Installing flask…
Collecting flask
...
...
Successfully installed Jinja2-2.10 MarkupSafe-1.1.0 Werkzeug-0.14.1 click-7.0 flask-1.0.2 itsdangerous-1.1.0
Adding flask to Pipfile's [packages]…
Pipfile.lock (e239e5) out of date, updating to (a79791)…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (e239e5)!
Installing dependencies from Pipfile.lock (e239e5)…
? ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 6/6 — 00:00:01
二、注册登录项目 创建过程
1、
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ sudo mkdir app
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ sudo chmod 777 app
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ vim __init__.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ ll
总用量 12
drwxrwxrwx 2 root root 4096 11月 14 18:39 ./
drwxrwxrwx 3 root root 4096 11月 14 18:31 ../
-rw-rw-r-- 1 chenchen chenchen 71 11月 14 18:39 __init__.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ cat __init__.py
from flask import Flask
app = Flask(__name__)
from app import routes
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ vim routes.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ cat routes.py
from app import app
@app.route('/')
@app.route('/index')
def index():
return "Hello, World!"
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ cd ..
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/$ vim run.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/$ cat run.py
from app import app
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ tree#展示项目结构图
.
├── app
│ ├── __init__.py
│ └── routes.py
├── Pipfile
├── Pipfile.lock
└── run.py
1 directory, 5 files
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$
运行程序
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ flask run
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [14/Nov/2018 18:53:29] "GET / HTTP/1.1" 200 -
Chrome浏览器输入:127.0.0.1:5000
运行OK。
接着实现git 分支管理:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git init
已初始化空的 Git 仓库于 /usr/ccdocs/myproject/.git/
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ ll
总用量 32
drwxrwxrwx 4 root root 4096 11月 14 22:36 ./
drwxr-xr-x 4 root root 4096 11月 14 15:58 ../
drwxrwxrwx 2 root root 4096 11月 14 18:50 app/
drwxrwxr-x 7 chenchen chenchen 4096 11月 14 22:36 .git/
-rw-rw-r-- 1 chenchen chenchen 150 11月 14 17:36 Pipfile
-rw-r--r-- 1 chenchen chenchen 4564 11月 14 17:37 Pipfile.lock
-rw-rw-r-- 1 chenchen chenchen 20 11月 14 18:44 run.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 master
尚无提交
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
Pipfile
Pipfile.lock
app/
run.py
提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪)
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add Pipfile
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add Pipfile.lock
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add app/
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add run.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git commit -m "搭建初始框架"
[master(根提交) 6596460] 搭建初始框架
5 files changed, 115 insertions(+)
create mode 100644 Pipfile
create mode 100644 Pipfile.lock
create mode 100644 app/__init__.py
create mode 100644 app/routes.py
create mode 100644 run.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 master
无文件要提交,干净的工作区
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git checkout -b v01
切换到一个新分支 'v01'
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v01
无文件要提交,干净的工作区
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git branch
master
* v01
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git checkout master
切换到分支 'master'
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git checkout -b v02
切换到一个新分支 'v02'
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git branch
master
v01
* v02
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v02
无文件要提交,干净的工作区
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$
2、模板定义
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v02
无文件要提交,干净的工作区
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ cd app
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ sudo mkdir templates
[sudo] chenchen 的密码:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ cd templates
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ sudo chmod 777 templates
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ cd templates
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app/templates$ vim index.html
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app/templates$ cat index.html
<html>
<head>
<title>{{ title }}-Home </title>
</head>
<body>
<h1>Hello, {{ user.username }}!</h1>
</body>
</html>
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app/templates$ cd ..
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ vim routes.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ cat routes.py
from app import app
from flask import render_template
@app.route('/')
@app.route('/index')
def index():
user = {'username':'chen'}
return render_template('index.html', title='首页', user=user)
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ cd ..
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ flask run
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [14/Nov/2018 23:14:18] "GET / HTTP/1.1" 200 -
在templates下定义一个基础模板base.html
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ cd app/templates
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app/templates$ vim base.html
代码如下:
<html>
<head>
<title>{{ title }}-云测平台</title>
</head>
<body>
<div>
<a href="#">登录</a> | <a href="#">注册</a>
</div>
<hr>
{% block content %}
{% endblock %}
</body>
</html>
有了模板就可以简化index.html了:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app/templates$ vim index.html
代码如下:
{% extends "base.html" %}
{% block content %}
<h1>这里是index页面,我在完成注册、登录功能</h1>
{% endblock %}
修改routes.py文件,代码如下:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app/templates$ cd ..
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ vim routes.py
from app import app
from flask import render_template
@app.route('/')
@app.route('/index')
def index():
return render_template('index.html', title='首页')
运行程序,效果如下:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ cd ..
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ flask run
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [15/Nov/2018 11:11:03] "GET / HTTP/1.1" 200 -
提交git操作,并将分支v02合并到master:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v02
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: app/routes.py
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
app/templates/
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add app/templates/
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add app/routes.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v02
要提交的变更:
(使用 "git reset HEAD <文件>..." 以取消暂存)
修改: app/routes.py
新文件: app/templates/base.html
新文件: app/templates/index.html
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git commit -m "使用模板"
[v02 a3858ea] 使用模板
3 files changed, 20 insertions(+), 2 deletions(-)
create mode 100644 app/templates/base.html
create mode 100644 app/templates/index.html
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v02
无文件要提交,干净的工作区
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git branch
master
v01
* v02
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git checkout master
切换到分支 'master'
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git merge v02
更新 6596460..a3858ea
Fast-forward
app/routes.py | 4 ++--
app/templates/base.html | 13 +++++++++++++
app/templates/index.html | 5 +++++
3 files changed, 20 insertions(+), 2 deletions(-)
create mode 100644 app/templates/base.html
create mode 100644 app/templates/index.html
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$
文件结构:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ tree
.
├── app
│ ├── __init__.py
│ ├── routes.py
│ └── templates
│ ├── base.html
│ └── index.html
├── Pipfile
├── Pipfile.lock
└── run.py
2 directories, 7 files
3、
新建分支v03
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ git status
位于分支 master
无文件要提交,干净的工作区
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ git checkout -b v03
切换到一个新分支 'v03'
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ git diff master
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ git status
位于分支 v03
无文件要提交,干净的工作区
创建Web表单,用于接受用户输入。
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ pipenv install flask-wtf
Installing flask-wtf…
Collecting flask-wtf
...
...
Successfully installed WTForms-2.2.1 flask-wtf-0.14.2
Adding flask-wtf to Pipfile's [packages]…
Pipfile.lock (111144) out of date, updating to (e239e5)…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (111144)!
Installing dependencies from Pipfile.lock (111144)…
? ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 8/8 — 00:00:01
根目录下,增加配置文件config.py
:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim config.py
import os
class Config(object):
SECRET_KEY = os.environ.get('SECRET_KEY') or 'you will never guess me'
Flask应用程序读取配置文件:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ cd app
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ vim __init__.py
from flask import Flask
from config import Config
app = Flask(__name__)
app.config.from_object(Config)
from app import routes
创建登录表单
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ vim forms.py
from flask_wtf import FlaskForm
from wtforms import StringField,PasswordField,BooleanField,SubmitField
from wtforms.validators import DataRequired
class LoginForm(FlaskForm):
username = StringField('用户名',validators=[DataRequired()])
password = PasswordField('密码',validators=[DataRequired()])
remember_me = BooleanField('记住我')
submit = SubmitField('登录')
将登录表单添加到HTML模板中,呈现在网页上。
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ cd templates
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app/templates$ vim login.html
login.html
代码:
{% extends "base.html" %}
{% block content %}
<h1>登录</h1>
<form action="" method="post" novalidate>
{{ form.hidden_tag() }}
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }}
</p>
<p>
{{ form.password.label }}<br>
{{ form.password(size=32) }}
</p>
<p>
{{ form.remember_me() }}
{{ form.remember_me.label }}
</p>
<p>
{{ form.submit() }}
</p>
{% endblock %}
编写一个登录的视图函数,用于渲染login.html
模板:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app/templates$ cd ..
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ vim routes.py
routes.py
代码:
from app import app
from flask import render_template
from app.forms import LoginForm
@app.route('/')
@app.route('/index')
def index():
return render_template('index.html', title='首页')
@app.route('/login')
def login():
form = LoginForm()
return render_template('login.html', title='登录', form=form)
基础模板base.html 导航栏增加登录链接:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app/templates$ vim base.html
<html>
<head>
<title>{{ title }}-云测平台</title>
</head>
<body>
<div>
<a href="/login">登录</a> | <a href="#">注册</a>
</div>
<hr>
{% block content %}
{% endblock %}
</body>
</html>
运行程序,查看效果:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ flask run
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [15/Nov/2018 12:27:13] "GET /login HTTP/1.1" 200 -
处理用户提交的数据,接受、验证用户的数据,routes.py
:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/routes.py
from app import app
from flask import render_template, flash, redirect
from app.forms import LoginForm
@app.route('/')
@app.route('/index')
def index():
return render_template('index.html', title='首页')
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
return redirect('index')
return render_template('login.html', title='登录', form=form)
增强字段验证,login.html
:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/templates/login.html
{% extends "base.html" %}
{% block content %}
<h1>登录</h1>
<form action="" method="post" novalidate>
{{ form.hidden_tag() }}
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }}<br>
{% for error in form.username.errors %}
<span style="color:red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.password.label }}<br>
{{ form.password(size=32) }}<br>
{% for error in form.password.errors %}
<span style="color:red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.remember_me() }}
{{ form.remember_me.label }}
</p>
<p>
{{ form.submit() }}
</p>
{% endblock %}
生成URL,使用url_for()
函数:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/templates/base.html
<html>
<head>
<title>{{ title }}-云测平台</title>
</head>
<body>
<div>
<a href="{{ url_for('login') }}">登录</a> | <a href="#">注册</a>
</div>
<hr>
{% block content %}
{% endblock %}
</body>
</html>
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/routes.py
from app import app
from flask import render_template, flash, redirect, url_for
from app.forms import LoginForm
@app.route('/')
@app.route('/index')
def index():
return render_template('index.html', title='首页')
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
return redirect(url_for('index'))
return render_template('login.html', title='登录', form=form)
项目结构:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ tree
.
├── app
│ ├── forms.py
│ ├── __init__.py
│ ├── routes.py
│ └── templates
│ ├── base.html
│ ├── index.html
│ └── login.html
├── config.py
├── Pipfile
├── Pipfile.lock
└── run.py
2 directories, 10 files
git操作:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v03
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: Pipfile
修改: Pipfile.lock
修改: app/__init__.py
修改: app/routes.py
修改: app/templates/base.html
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
app/forms.py
app/templates/login.html
config.py
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add app/forms.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add app/templates/login.html
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add config.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add app/forms.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add app/templates/login.html
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add config.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add Pipfile
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add Pipfile.lock
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add app/__init__.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add app/routes.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add app/templates/base.html
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git commit -m "完成web表单"
[v03 34f9e09] 完成web表单
8 files changed, 68 insertions(+), 3 deletions(-)
create mode 100644 app/forms.py
create mode 100644 app/templates/login.html
create mode 100644 config.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v03
无文件要提交,干净的工作区
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git checkout master
切换到分支 'master'
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git merge v03
更新 a3858ea..34f9e09
Fast-forward
Pipfile | 1 +
Pipfile.lock | 17 ++++++++++++++++-
app/__init__.py | 2 ++
app/forms.py | 9 +++++++++
app/routes.py | 10 +++++++++-
app/templates/base.html | 2 +-
app/templates/login.html | 27 +++++++++++++++++++++++++++
config.py | 3 +++
8 files changed, 68 insertions(+), 3 deletions(-)
create mode 100644 app/forms.py
create mode 100644 app/templates/login.html
create mode 100644 config.py
4、数据库
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git checkout master
切换到分支 'master'
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git checkout -b v04
切换到一个新分支 'v04'
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v04
无文件要提交,干净的工作区
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git branch
master
v01
v02
v03
* v04
安装sqlite3:在开发过程中使用sqlite3,在生产服务器上部署时可使用MySQL,无需改变应用程序。
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ sudo apt-get install sqlite3
[sudo] chenchen 的密码:
正在读取软件包列表... 完成
正在分析软件包的依赖关系树
正在读取状态信息... 完成
...
...
正准备解包 .../sqlite3_3.11.0-1ubuntu1_amd64.deb ...
正在解包 sqlite3 (3.11.0-1ubuntu1) ...
正在处理用于 man-db (2.7.5-1) 的触发器 ...
正在设置 sqlite3 (3.11.0-1ubuntu1) ...
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ sqlite3 -version
3.11.0 2016-02-15 17:29:24 3d862f207e3adc00f78066799ac5a8c282430a5f
安装Flask-SQLAlchemy:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ pipenv install flask-sqlalchemy
...
...
Successfully installed SQLAlchemy-1.2.14 flask-sqlalchemy-2.3.2
Adding flask-sqlalchemy to Pipfile's [packages]…
Pipfile.lock (3940c2) out of date, updating to (111144)…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (3940c2)!
Installing dependencies from Pipfile.lock (3940c2)…
? ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 10/10 — 00:00:02
Flask-SQLAlchemy配置:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim config.py
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config(object):
SECRET_KEY = os.environ.get('SECRET_KEY') or 'you will never guess me'
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URI') or 'sqlite:///' +os.path.join(basedir, 'app.db')
SQLALCHEMY_TRACK_MODIFICATIONS = False
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/__init__.py
from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
from app import routes, models
为用户创建数据库模型
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/models.py
from app import db
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(64), index=True, unique=True)
password_hash = db.Column(db.String(128))
def __repr__(self):
return '<User {}>'.format(self.username)
测试一下用户数据库模型:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ python
Python 3.5.2 (default, Nov 23 2017, 16:37:01)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from app.models import User
>>> u = User(username='chenchen', email='chenchen@eaxmple.com')
>>> u
<User chenchen>
>>> exit()
创建shell上下文,方便在应用程序上下文中启动Python解释器:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim run.py
from app import app,db
from app.models import User
@app.shell_context_processor
def make_shell_context():
return {'db':db, 'User':User}
添加了shell 上下文处理器功能后,我们可以方便地使用数据库实体,而无需导入它们:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ export FLASK_APP=run.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ flask shell
Python 3.5.2 (default, Nov 23 2017, 16:37:01)
[GCC 5.4.0 20160609] on linux
App: app [production]
Instance: /usr/ccdocs/myproject/instance
>>> db
<SQLAlchemy engine=sqlite:usr/ccdocs/myproject/app.db>
>>> User
<class 'app.models.User'>
>>> exit()
创建一个sqlite3 数据库:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ sqlite3 app.db
SQLite version 3.11.0 2016-02-15 17:29:24
Enter ".help" for usage hints.
sqlite> CREATE TABLE user (id INTEGER PRIMARY KEY AUTOINCREMENT, username VARCHAR(64), email VARCHAR(64), password_hash VARCHAR(128));
sqlite> .quit
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ flask shell
Python 3.5.2 (default, Nov 23 2017, 16:37:01)
[GCC 5.4.0 20160609] on linux
App: app [production]
Instance: /usr/ccdocs/myproject/instance
>>> u = User(username='lvlv', email='lvlv@example.com')
>>> db.session.add(u)
>>> db.session.commit()
>>> users = User.query.all()
>>> users
[<User lvlv>]
>>> exit()
项目结构:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ tree
.
├── app
│ ├── forms.py
│ ├── __init__.py
│ ├── models.py
│ ├── routes.py
│ └── templates
│ ├── base.html
│ ├── index.html
│ └── login.html
├── app.db
├── config.py
├── Pipfile
├── Pipfile.lock
└── run.py
2 directories, 12 files
git操作:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v04
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: Pipfile
修改: Pipfile.lock
修改: app/__init__.py
修改: config.py
修改: run.py
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
app.db
app/models.py
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add app.db app/models.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add Pipfile Pipfile.lock app/__init__.py config.py run.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git commit -m "添加User模型"
[v04 3e424f2] 添加User模型
7 files changed, 40 insertions(+), 3 deletions(-)
create mode 100644 app.db
create mode 100644 app/models.py
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v04
无文件要提交,干净的工作区
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git checkout master
切换到分支 'master'
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git merge v04
更新 34f9e09..3e424f2
Fast-forward
Pipfile | 1 +
Pipfile.lock | 16 +++++++++++++++-
app.db | Bin 0 -> 3072 bytes
app/__init__.py | 4 +++-
app/models.py | 10 ++++++++++
config.py | 5 +++++
run.py | 7 ++++++-
7 files changed, 40 insertions(+), 3 deletions(-)
create mode 100644 app.db
create mode 100644 app/models.py
5、用户登录
git 新建分支:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 master
无文件要提交,干净的工作区
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git checkout -b v05
切换到一个新分支 'v05'
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v05
无文件要提交,干净的工作区
给用户模型的password_hash字段实现密码哈希:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/models.py
from app import db
from werkzeug.security import generate_password_hash, check_password_hash
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(64), index=True, unique=True)
password_hash = db.Column(db.String(128))
def __repr__(self):
return '<User {}>'.format(self.username)
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
安装Flask-Login:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ pipenv install flask-login
Installing flask-login…
...
...
Successfully installed flask-login-0.4.1
Adding flask-login to Pipfile's [packages]…
Pipfile.lock (8930f0) out of date, updating to (3940c2)…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (8930f0)!
Installing dependencies from Pipfile.lock (8930f0)…
初始化Flask-Login:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/__init__.py
from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
login = LoginManager(app)
from app import routes, models
为Flask-Login准备用户模型、用户加载器功能:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/models.py
from app import db,login
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(64), index=True, unique=True)
password_hash = db.Column(db.String(128))
def __repr__(self):
return '<User {}>'.format(self.username)
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
@login.user_loader
def load_user(id):
return User.query.get(int(id))
修改用户登录视图函数:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/routes.py
from app import app
from flask import render_template, flash, redirect, url_for
from app.forms import LoginForm
from flask_login import current_user, login_user
from app.models import User
@app.route('/')
@app.route('/index')
def index():
return render_template('index.html', title='首页')
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('index')
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is None or not user.check_password(form.password.data):
flash('无效的用户名或密码')
return redirect(url_for('login'))
login_user(user, remember=form.remember_me.data)
return redirect(url_for('index'))
return render_template('login.html', title='登录', form=form)
增加用户退出视图函数:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/routes.py
from app import app
from flask import render_template, flash, redirect, url_for
from app.forms import LoginForm
from flask_login import current_user, login_user, logout_user
from app.models import User
@app.route('/')
@app.route('/index')
def index():
return render_template('index.html', title='首页')
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('index')
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is None or not user.check_password(form.password.data):
flash('无效的用户名或密码')
return redirect(url_for('login'))
login_user(user, remember=form.remember_me.data)
return redirect(url_for('index'))
return render_template('login.html', title='登录', form=form)
@app.route('/logout')
def logout():
logout_user()
return redirect(url_for('index'))
给基础模板base.html增加条件登录和退出链接:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/templates/base.html
<html>
<head>
<title>{{ title }}-云测平台</title>
</head>
<body>
<div>
{% if current_user.is_anonymous %}
<a href="{{ url_for('login') }}">登录</a> | <a href="#">注册</a>
{% else %}
<a href="{{ url_for('logout') }}">退出</a>
{% endif %}
</div>
<hr>
{% block content %}
{% endblock %}
</body>
</html>
要求用户登录:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/__init__.py
from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
login = LoginManager(app)
login.login_view = 'login'
from app import routes, models
app/routes.py
给index视图函数添加@login_required装饰器,并重定向到next页面:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/routes.py
from app import app
from flask import render_template, flash, redirect, url_for, request
from werkzeug.urls import url_parse
from app.forms import LoginForm
from flask_login import current_user, login_user, logout_user, login_required
from app.models import User
@app.route('/')
@app.route('/index')
@login_required
def index():
return render_template('index.html', title='首页')
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('index'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is None or not user.check_password(form.password.data):
flash('无效的用户名或密码')
return redirect(url_for('login'))
login_user(user, remember=form.remember_me.data)
next_page = request.args.get('next')
if not next_page or url_parse(next_page).netloc != '':
next_page = url_for('index')
return redirect(next_page)
return render_template('login.html', title='登录', form=form)
@app.route('/logout')
def logout():
logout_user()
return redirect(url_for('index'))
分别在基础模板导航栏、index模板中显示登录用户:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/templates/base.html
<html>
<head>
<title>{{ title }}-云测平台</title>
</head>
<body>
<div>
{% if current_user.is_anonymous %}
<a href="{{ url_for('login') }}">登录</a> | <a href="#">注册</a>
{% else %}
[{{ current_user.username }}] | <a href="{{ url_for('logout') }}">退出</a>
{% endif %}
</div>
<hr>
{% block content %}
{% endblock %}
</body>
</html>
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/templates/index.html
{% extends "base.html" %}
{% block content %}
<h1>这里是index页面,我在完成注册、登录功能</h1>
<p>我是 {{ current_user.username}}</p>
{% endblock %}
改善体验,如果输入密码或用户名,弹出提示消息:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/templates/base.html
<html>
<head>
<title>{{ title }}-云测平台</title>
</head>
<body>
<div>
{% if current_user.is_anonymous %}
<a href="{{ url_for('login') }}">登录</a> | <a href="{{ url_for('register') }}">注册</a>
{% else %}
[{{ current_user.username }}] | <a href="{{ url_for('logout') }}">退出</a>
{% endif %}
</div>
<hr>
{% with messages=get_flashed_messages() %}
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block content %}
{% endblock %}
</body>
</html>
用户注册:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/forms.py
from flask_wtf import FlaskForm
from wtforms import StringField,PasswordField,BooleanField,SubmitField
from wtforms.validators import DataRequired,ValidationError,Email,EqualTo
from app.models import User
class LoginForm(FlaskForm):
username = StringField('用户名',validators=[DataRequired()])
password = PasswordField('密码',validators=[DataRequired()])
remember_me = BooleanField('记住我')
submit = SubmitField('登录')
class RegistrationForm(FlaskFrom):
username = StringField('用户名', validators=[DataRequired()])
email = StringField('邮箱', validators=[DataRequired()])
password = PasswordField('密码', validators=[DataRequired()])
password2 = PasswordField('重输一次密码', validators=[DataRequired(), EqualTo('password')])
submit = SubmitField('注册')
def validate_username(self,username):
user = User.query.filter_by(username=username.data).first()
if user is not None:
raise ValidationError('用户名被占用')
def validate_email(self, email):
user = User.query.filter_by(email=email.data).first()
if user is not None:
raise ValidationError('邮箱被占用')
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/templates/register.html
{% extends "base.html" %}
{% block content %}
<h1>用户注册</h1>
<form action="" method="post">
{{ form.hidden_tag() }}
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }}<br>
{% for error in form.username.errors %}
<span style="color:red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.email.label }}<br>
{{ form.email(size=64) }}<br>
{% for error in form.email.error %}
<span style="color:red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.password.label }}<br>
{{ form.password(size=32) }}<br>
{% for error in form.password.errors %}
<span style="color:red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.password2.label }}<br>
{{ form.password2(size=32) }}<br>
{% for error in form.password2.errors %}
<span style="color:red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>{{ form.submit() }}</p>
</form>
{% endblock %}
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/templates/login.html
{% extends "base.html" %}
{% block content %}
<h1>登录</h1>
<form action="" method="post" novalidate>
{{ form.hidden_tag() }}
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }}<br>
{% for error in form.username.errors %}
<span style="color:red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.password.label }}<br>
{{ form.password(size=32) }}<br>
{% for error in form.password.errors %}
<span style="color:red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.remember_me() }}
{{ form.remember_me.label }}
</p>
<p>
{{ form.submit() }}
</p>
</form>
<p>新用户?<a href="{{ url_for('register') }}">点击注册</a></p>
{% endblock %}
添加用户注册视图函数:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/routes.py
from app import app,db
from flask import render_template, flash, redirect, url_for, request
from werkzeug.urls import url_parse
from app.forms import LoginForm,RegistrationForm
from flask_login import current_user, login_user, logout_user, login_required
from app.models import User
@app.route('/')
@app.route('/index')
@login_required
def index():
return render_template('index.html', title='首页')
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('index'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is None or not user.check_password(form.password.data):
flash('无效的用户名或密码')
return redirect(url_for('login'))
login_user(user, remember=form.remember_me.data)
next_page = request.args.get('next')
if not next_page or url_parse(next_page).netloc != '':
next_page = url_for('index')
return redirect(next_page)
return render_template('login.html', title='登录', form=form)
@app.route('/logout')
def logout():
logout_user()
return redirect(url_for('index'))
@app.route('/register', methods=['GET','POST'])
def register():
if current_user.is_authenticated:
return redirect(url_for('index'))
form = RegistrationForm()
if form.validate_on_submit():
user = User(username=form.username.data, email=form.email.data)
user.set_password(form.password.data)
db.session.add(user)
db.session.commit()
flash('恭喜,注册成功')
return redirect(url_for('login'))
return render_template('register.html', title='注册', form=form)
git操作:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v05
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: Pipfile
修改: Pipfile.lock
修改: app.db
修改: app/__init__.py
修改: app/forms.py
修改: app/models.py
修改: app/routes.py
修改: app/templates/base.html
修改: app/templates/index.html
修改: app/templates/login.html
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
app/templates/register.html
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add Pipfile Pipfile.lock app.db app/__init__.py app/forms.py app/models.py app/routes.py app/templates/base.html app/templates/index.html app/templates/login.html app/templates/register.html
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v05
要提交的变更:
(使用 "git reset HEAD <文件>..." 以取消暂存)
修改: Pipfile
修改: Pipfile.lock
修改: app.db
修改: app/__init__.py
修改: app/forms.py
修改: app/models.py
修改: app/routes.py
修改: app/templates/base.html
修改: app/templates/index.html
修改: app/templates/login.html
新文件: app/templates/register.html
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git commit -m "完成用户登录"
[v05 71285d0] 完成用户登录
11 files changed, 136 insertions(+), 9 deletions(-)
create mode 100644 app/templates/register.html
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v05
无文件要提交,干净的工作区
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git checkout master
切换到分支 'master'
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git merge v05
更新 3e424f2..7857ae5
Fast-forward
Pipfile | 1 +
Pipfile.lock | 9 ++++++++-
app.db | Bin 3072 -> 3072 bytes
app/__init__.py | 3 +++
app/forms.py | 19 ++++++++++++++++++-
app/models.py | 16 ++++++++++++++--
app/routes.py | 42 ++++++++++++++++++++++++++++++++++++++----
app/templates/base.html | 15 ++++++++++++++-
app/templates/index.html | 1 +
app/templates/login.html | 2 ++
app/templates/register.html | 37 +++++++++++++++++++++++++++++++++++++
11 files changed, 136 insertions(+), 9 deletions(-)
create mode 100644 app/templates/register.html
项目结构:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ tree
.
├── app
│ ├── forms.py
│ ├── __init__.py
│ ├── models.py
│ ├── routes.py
│ └── templates
│ ├── base.html
│ ├── index.html
│ ├── login.html
│ └── register.html
├── app.db
├── config.py
├── Pipfile
├── Pipfile.lock
└── run.py
2 directories, 13 files
6、蓝图
git操作,新建分支:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 master
无文件要提交,干净的工作区
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git checkout -b v06
切换到一个新分支 'v06'
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git checkout -b v06
切换到一个新分支 'v06'
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ cd app
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ sudo mkdir auth
[sudo] chenchen 的密码:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ sudo chmod 777 auth
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ sudo mv routes.py forms.py auth
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ cd templates
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app/templates$ sudo mkdir auth
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app/templates$ sudo chmod 777 auth
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app/templates$ sudo mv login.html register.html auth
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app/templates$ cd ..
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ cd auth
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app/auth$ vim __init__.py
app/auth/__init__.py代码:
from flask import Blueprint
bp = Blueprint('auth', __name__)
from app.auth import routes
修改app/__init__.py
:应用工厂模式
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/__init__.py
import os
import logging
from logging.handlers import RotatingFileHandler
from flask import Flask,request,current_app
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
db = SQLAlchemy()
login = LoginManager()
login.login_view = 'auth.login'
login.login_message = '请先登录以进入该页面'
bootstrap = Bootstrap()
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(config_class)
db.init_app(app)
login.init_app(app)
bootstrap.init_app(app)
from app.auth import bp as auth_bp
app.register_blueprint(auth_bp, url_prefix='/auth')
from app.main import bp as main_bp
app.register_blueprint(main_bp)
if not app.debug and not app.testing:
if not os.path.exists('logs'):
os.mkdir('logs')
file_handler = RotatingFileHandler('logs/app.log', maxBytes=10240, backupCount=10)
file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s:%(message)s''[in %(pathname)s:%(lineno)d]'))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)
app.logger.info('程序启动')
return app
from app import models
修改app/auth/routes.py文件:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/auth/routes.py
from app import db
from flask import render_template, flash, redirect, url_for, request
from werkzeug.urls import url_parse
from app.auth.forms import LoginForm,RegistrationForm
from flask_login import current_user, login_user, logout_user
from app.auth import bp
from app.models import User
@bp.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('main.index'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is None or not user.check_password(form.password.data):
flash('无效的用户名或密码')
return redirect(url_for('auth.login'))
login_user(user, remember=form.remember_me.data)
next_page = request.args.get('next')
if not next_page or url_parse(next_page).netloc != '':
next_page = url_for('main.index')
return redirect(next_page)
return render_template('auth/login.html', title='登录', form=form)
@bp.route('/logout')
def logout():
logout_user()
return redirect(url_for('main.index'))
@bp.route('/register', methods=['GET','POST'])
def register():
if current_user.is_authenticated:
return redirect(url_for('main.index'))
form = RegistrationForm()
if form.validate_on_submit():
user = User(username=form.username.data, email=form.email.data)
user.set_password(form.password.data)
db.session.add(user)
db.session.commit()
flash('恭喜,注册成功')
return redirect(url_for('auth.login'))
return render_template('auth/register.html', title='注册', form=form)
修改app/templates/auth/login.html
:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/templates/auth/login.html
{% extends "base.html" %}
{% block content %}
<h1>登录</h1>
<form action="" method="post" novalidate>
{{ form.hidden_tag() }}
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }}<br>
{% for error in form.username.errors %}
<span style="color:red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.password.label }}<br>
{{ form.password(size=32) }}<br>
{% for error in form.password.errors %}
<span style="color:red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.remember_me() }}
{{ form.remember_me.label }}
</p>
<p>
{{ form.submit() }}
</p>
</form>
<p>新用户?<a href="{{ url_for('auth.register') }}">点击注册</a></p>
{% endblock %}
修改app/templates/auth/register.html
:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/templates/auth/register.html
{% extends "base.html" %}
{% block content %}
<h1>用户注册</h1>
<form action="" method="post">
{{ form.hidden_tag() }}
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }}<br>
{% for error in form.username.errors %}
<span style="color:red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.email.label }}<br>
{{ form.email(size=64) }}<br>
{% for error in form.email.error %}
<span style="color:red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.password.label }}<br>
{{ form.password(size=32) }}<br>
{% for error in form.password.errors %}
<span style="color:red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.password2.label }}<br>
{{ form.password2(size=32) }}<br>
{% for error in form.password2.errors %}
<span style="color:red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>{{ form.submit() }}</p>
</form>
{% endblock %}
应用程序 main 蓝图
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ cd app
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ sudo mkdir main
[sudo] chenchen 的密码:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ sudo chmod 777 main
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ vim main/__init__.py
代码:
from flask import Blueprint
bp = Blueprint('main', __name__)
from app.main import routes
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject/app$ vim main/routes.py
from flask import render_template
from flask_login import current_user,login_required
from app import db
from app.main import bp
@bp.route('/', methods=['GET', 'POST'])
@bp.route('/index', methods=['GET', 'POST'])
@login_required
def index():
return render_template('index.html', title='首页')
修改run.py
:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim run.py
from app import create_app, db
from app.models import User
app = create_app()
@app.shell_context_processor
def make_shell_context():
return {'db':db, 'User':User}
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/models.py
from app import db,login
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(64), index=True, unique=True)
password_hash = db.Column(db.String(128))
def __repr__(self):
return '<User {}>'.format(self.username)
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
@login.user_loader
def load_user(id):
return User.query.get(int(id))
修改base.html
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/templates/base.html
<html>
<head>
<title>{{ title }}-云测平台</title>
</head>
<body>
<div>
{% if current_user.is_anonymous %}
<a href="{{ url_for('auth.login') }}">登录</a> | <a href="{{ url_for('auth.register') }}">注册</a>
{% else %}
[{{ current_user.username }}] | <a href="{{ url_for('auth.logout') }}">退出</a>
{% endif %}
</div>
<hr>
{% with messages=get_flashed_messages() %}
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block content %}
{% endblock %}
</body>
</html>
修改index.html
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim app/templates/index.html
{% extends "base.html" %}
{% block content %}
<h1>这里是index页面,已完成注册、登录功能</h1><br>
<h2>我是 {{ current_user.username}}</h2>
{% endblock %}
git操作:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ touch .gitignore
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ vim .gitignore
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v06
要提交的变更:
(使用 "git reset HEAD <文件>..." 以取消暂存)
新文件: app/auth/__init__.py
新文件: app/auth/forms.py
新文件: app/auth/routes.py
新文件: app/main/__init__.py
新文件: app/main/routes.py
新文件: app/templates/auth/login.html
新文件: app/templates/auth/register.html
新文件: logs/app.log
新文件: logs/app.log.1
新文件: logs/app.log.2
尚未暂存以备提交的变更:
(使用 "git add/rm <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: app.db
修改: app/__init__.py
删除: app/forms.py
修改: app/models.py
删除: app/routes.py
修改: app/templates/base.html
修改: app/templates/index.html
删除: app/templates/login.html
删除: app/templates/register.html
修改: run.py
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
.gitignore
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git add 各个文件
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git commit -m "用蓝图重构"
[v06 349d7a2] 用蓝图重构
17 files changed, 436 insertions(+), 65 deletions(-)
create mode 100644 .gitignore
rewrite app/__init__.py (63%)
create mode 100644 app/auth/__init__.py
rename app/{ => auth}/forms.py (100%)
rename app/{ => auth}/routes.py (55%)
create mode 100644 app/main/__init__.py
create mode 100644 app/main/routes.py
rename app/templates/{ => auth}/login.html (87%)
rename app/templates/{ => auth}/register.html (98%)
rewrite app/templates/base.html (98%)
create mode 100644 logs/app.log
create mode 100644 logs/app.log.1
create mode 100644 logs/app.log.2
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 v06
无文件要提交,干净的工作区
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git checkout master
切换到分支 'master'
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git branch
* master
v01
v02
v03
v04
v05
v06
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git merge v06
更新 7857ae5..349d7a2
Fast-forward
.gitignore | 8 +++++++
app.db | Bin 3072 -> 3072 bytes
app/__init__.py | 41 +++++++++++++++++++++++++------
app/auth/__init__.py | 5 ++++
app/{ => auth}/forms.py | 0
app/{ => auth}/routes.py | 35 ++++++++++++---------------
app/main/__init__.py | 5 ++++
app/main/routes.py | 11 +++++++++
app/models.py | 2 +-
app/templates/{ => auth}/login.html | 4 ++--
app/templates/{ => auth}/register.html | 2 +-
app/templates/base.html | 50 +++++++++++++++++++-------------------
app/templates/index.html | 4 ++--
logs/app.log | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
logs/app.log.1 | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
logs/app.log.2 | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
run.py | 4 +++-
17 files changed, 430 insertions(+), 59 deletions(-)
create mode 100644 .gitignore
create mode 100644 app/auth/__init__.py
rename app/{ => auth}/forms.py (100%)
rename app/{ => auth}/routes.py (55%)
create mode 100644 app/main/__init__.py
create mode 100644 app/main/routes.py
rename app/templates/{ => auth}/login.html (87%)
rename app/templates/{ => auth}/register.html (98%)
create mode 100644 logs/app.log
create mode 100644 logs/app.log.1
create mode 100644 logs/app.log.2
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ git status
位于分支 master
无文件要提交,干净的工作区
项目结构图:
(myproject) chenchen@chenchen-ubuntu:/usr/ccdocs/myproject$ tree
.
├── app
│ ├── auth
│ │ ├── forms.py
│ │ ├── __init__.py
│ │ └── routes.py
│ ├── __init__.py
│ ├── main
│ │ ├── __init__.py
│ │ └── routes.py
│ ├── models.py
│ └── templates
│ ├── auth
│ │ ├── login.html
│ │ └── register.html
│ ├── base.html
│ └── index.html
├── app.db
├── config.py
├── logs
│ ├── app.log
│ ├── app.log.1
│ └── app.log.2
├── Pipfile
├── Pipfile.lock
└── run.py
6 directories, 19 files