02: flask 使用举例
1.1 项目说明
https://github.com/rickyyangrui/Flask_web_demo1
1、项目文件结构
2、项目主文件
cssmin==0.2.0
Flask==0.11.1
Flask-Admin==1.4.2
Flask-Assets==0.12
Flask-Avatar==0.1.0
Flask-BabelEx==0.9.3
Flask-Bootstrap==3.3.7.0
Flask-Cache==0.13.1
Flask-Login==0.3.2
Flask-Mail==0.9.1
Flask-Maple==0.4.7
Flask-Migrate==1.8.0
flask-msearch==0.1.2
Flask-Principal==0.4.0
Flask-Script==2.0.5
Flask-SQLAlchemy==2.2
Flask-WTF==0.14.2
gevent==1.1.1
greenlet==0.4.12
gunicorn==19.4.5
html5lib==0.9999999
itsdangerous==0.24
Jinja2==2.8
Mako==1.0.7
MarkupSafe==1.0
MySQL-python==1.2.5
Pillow==3.2.0
psycopg2==2.7.3.1
PyMySQL==0.7.11
python-dateutil==2.6.1
python-editor==1.0.3
pytz==2017.2
six==1.10.0
speaklater==1.3
SQLAlchemy==1.1.14
visitor==0.1.3
webassets==0.12.1
Werkzeug==0.12.2
Whoosh==2.7.4
WTForms==2.1
requirements.txt
#encoding: utf-8 from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from platform import app
from exts import db
from models import User, Question, Answer manager = Manager(app) # 使用Migrate绑定app和db
migrate = Migrate(app, db) # 添加迁移脚本的命令到manager中
manager.add_command('db', MigrateCommand) if __name__ == '__main__':
manager.run()
manage.py
#encoding: utf-8
import os DEBUG = True SECRET_KEY = os.urandom(24) SQLALCHEMY_DATABASE_URI = 'mysql://root:1@localhost/testdb'
SQLALCHEMY_TRACK_MODIFICATIONS = True
config.py
#encoding: utf-8 from flask import Flask, render_template, request, redirect, url_for, session
import config
from models import User, Question, Answer
from exts import db
from decorators import login_required
from sqlalchemy import or_ app = Flask(__name__)
app.config.from_object(config)
db.init_app(app) @app.route('/')
def index():
context = {
'questions': Question.query.order_by('-create_time').all()
}
return render_template('index.html', **context) @app.route('/login/', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
else:
telephone = request.form.get('telephone')
password = request.form.get('password')
user = User.query.filter(User.telephone == telephone, User.password ==
password).first()
if user:
session['user_id'] = user.id
# 如果想在31天内都不需要登录
session.permanent = True
return redirect(url_for('index'))
else:
return u'手机号码或者密码错误,请确认好在登录' @app.route('/regist/', methods=['GET', 'POST'])
def regist():
if request.method == 'GET':
return render_template('regist.html')
else:
telephone = request.form.get('telephone')
username = request.form.get('username')
password1 = request.form.get('password1')
password2 = request.form.get('password2') # 手机号码验证,如果被注册了就不能用了
user = User.query.filter(User.telephone == telephone).first()
if user:
return u'该手机号码被注册,请更换手机'
else:
# password1 要和password2相等才可以
if password1 != password2:
return u'两次密码不相等,请核实后再填写'
else:
user = User(telephone=telephone, username=username, password=password1)
db.session.add(user)
db.session.commit()
# 如果注册成功,就让页面跳转到登录的页面
return redirect(url_for('login')) # 判断用户是否登录,只要我们从session中拿到数据就好了 注销函数
@app.route('/logout/')
def logout():
# session.pop('user_id')
# del session('user_id')
session.clear()
return redirect(url_for('login')) @app.route('/question/', methods=['GET', 'POST'])
@login_required
def question():
if request.method == 'GET':
return render_template('question.html')
else:
title = request.form.get('title')
content = request.form.get('content')
question = Question(title=title, content=content)
user_id = session.get('user_id')
user = User.query.filter(User.id == user_id).first()
question.author = user
db.session.add(question)
db.session.commit()
return redirect(url_for('index')) @app.route('/detail/<question_id>/')
def detail(question_id):
question_model = Question.query.filter(Question.id == question_id).first()
return render_template('detail.html', question=question_model) @app.route('/add_answer/', methods=['POST'])
@login_required
def add_answer():
content = request.form.get('answer_content')
question_id = request.form.get('question_id')
answer = Answer(content=content)
user_id = session['user_id']
user = User.query.filter(User.id == user_id).first()
answer.author = user
question = Question.query.filter(Question.id == question_id).first()
answer.question = question
db.session.add(answer)
db.session.commit()
return redirect(url_for('detail', question_id=question_id)) @app.route('/search/')
def search():
q = request.args.get('q')
# title, content
# 或 查找方式(通过标题和内容来查找)
# questions = Question.query.filter(or_(Question.title.contains(q),
# Question.content.constraints(q))).order_by('-create_time')
# 与 查找(只能通过标题来查找)
questions = Question.query.filter(Question.title.contains(q), Question.content.contains(q))
return render_template('index.html', questions=questions) # 钩子函数(注销)
@app.context_processor
def my_context_processor():
user_id = session.get('user_id')
if user_id:
user = User.query.filter(User.id == user_id).first()
if user:
return {'user': user}
return {} if __name__ == '__main__':
app.run(debug=True)
platform.py 视图函数
#encoding: utf-8 from exts import db
from datetime import datetime class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
telephone = db.Column(db.String(11), nullable=False)
username = db.Column(db.String(50), nullable=False)
password = db.Column(db.String(100), nullable=False) class Question(db.Model):
__tablename__ = 'question'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(100), nullable=False)
content = db.Column(db.Text, nullable=False)
# now()获取的是服务器第一次运行的时间
# now就是每次创建一个模型的时候,都获取当前的时间
create_time = db.Column(db.DateTime, default=datetime.now)
author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
author = db.relationship('User', backref=db.backref('questions')) class Answer(db.Model):
__tablename__ = 'answer'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
content = db.Column(db.Text, nullable=False)
create_time = db.Column(db.DateTime, default=datetime.now)
question_id = db.Column(db.Integer, db.ForeignKey('question.id'))
author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
question = db.relationship('Question', backref=db.backref('answers', order_by=id.desc()))
author = db.relationship('User', backref=db.backref('answers'))
models.py
#encoding: utf-8 from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy()
exts.py 配置flask_sqlalchemy操作数据库
#encoding: utf-8 from functools import wraps
from flask import session, redirect, url_for # 登录限制的装饰器
def login_required(func): @wraps(func)
def qingwa(*args, **kwargs):
if session.get('user_id'):
return func(*args, **kwargs)
else:
return redirect(url_for('login')) return qingwa
decorators.py 登录装饰器
3、模板文件 (templates 文件夹先创建下面文件)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}-青蛙课堂问答平台</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity=
"sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <script> src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"</script> <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity=
"sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin=
"anonymous"></script> <link rel="stylesheet" href="{{ url_for('static', filename='css/base.css') }}"> {% block head %}{% endblock %} </head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<!-- 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="#">
<img class="logo" src="{{ url_for('static', filename= 'images/qingwalogo.jpg') }}" alt="">
</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="/">首页 <span class="sr-only">(current)</span></a></li>
<li><a href="{{ url_for('question') }}">发布问答</a></li>
</ul>
<form class="navbar-form navbar-left" action="{{ url_for('search') }}" method="get">
<div class="form-group">
<input name="q" type="text" class="form-control" placeholder="请输入关键字">
</div>
<button type="submit" class="btn btn-default">查找</button>
</form>
<ul class="nav navbar-nav navbar-right">
{% if user %}
<li><a href="#">{{ user.username }}</a></li>
<li><a href="{{ url_for('logout') }}">注销</a></li>
{% else %}
<li><a href="{{ url_for('login') }}">登录</a></li>
<li><a href="{{ url_for('regist') }}">注册</a></li>
{% endif %}
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav> <div class='main'>
{% block main %}{% endblock %}
</div> </body>
</html>
base.html
{% extends 'base.html' %} {% block title %}详情-{% endblock %} {% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/detail.css') }}"> {% endblock %} {% block main %}
<h3 class="page-title">{{ question.title }}</h3>
<p class="question-info">
<sqan>作者: {{ question.author.username }}</sqan>
<span>时间: {{ question.create_time }}</span>
</p>
<hr>
<p class="question-content">{{ question.content }}</p>
<hr>
<h4>评论: (0)</h4>
<form action="{{ url_for('add_answer') }}" method="post">
<div class="form-group">
<input name="answer_content" type="text" class="from-control" placeholder="请填写评论">
<input type="hidden" name="question_id" value="{{ question.id }}">
</div>
<div class="form-group" style="text-align: right;">
<button class="btn btn-primary">立即评论</button>
</div>
</form>
<ul class="answer-list">
{% for answer in question.answers %}
<li>
<div class="user-info">
<img src="{{ url_for('static', filename='images/qingwalogo.jpg') }}" alt=""
class="avatar">
<span class="username">{{ answer.author.username }}</span>
<span class="create-time">{{ answer.create_time }}</span>
</div>
<p class="answer-content">{{ answer.content }}</p>
</li>
{% endfor %}
</ul>
{% endblock %}
detail.html
{% extends 'base.html' %} {% block title %}首页{% endblock %} {% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/index.css') }}">
{% endblock %} {% block main %}
<ul>
{% for question in questions %}
<li>
<div class="avatar-group">
<img src="{{ url_for('static', filename='images/qingwalogo.jpg') }}"
alt="" class="avatar">
</div>
<div class="question-group">
<p class="question-title"><a href="{{ url_for('detail',question_id=question.id)
}}">{{ question.title }}</a></p>
<p class="question-content">{{ question.content }}</p>
<div class="question-info">
<span class="question-author">{{ question.author.username }}</span>
<span class="question-time">{{ question.create_time }}</span>
</div>
</div>
</li>
{% endfor %}
</ul>
{% endblock %}
index.html
{% extends 'base.html' %} {% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/login_regist.css') }}">
{% endblock %} {% block main %}
<h3 class="page-title">登录</h3>
<form action="" method="POST">
<div class='form-container'>
<div class='form-group'>
<input type="text" class="form-control" placeholder="手机号码"
name="telephone">
</div>
<div class='form-group'>
<input type="password" class="form-control" placeholder="密码"
name="password">
</div>
<div class="form-group">
<button class="btn btn-primary btn-block">登录</button>
</div>
</div>
</form> {% endblock %}
login.html
{% extends 'base.html' %} {% block title %}发布问答{% endblock %} {% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/question.css') }}">
{% endblock %} {% block main %}
<h3 class="page-title">发布问答</h3>
<form action="" method="post">
<div class='form-container'>
<div class="form-group">
<input type="text" placeholder="请输入标题" name="title"
class="form-control">
</div>
<div class="form-group">
<textarea name="content" rows="5" placeholder="请输入内容" class="form-control"></textarea>
</div>
<div class="form-group">
<button class="btn btn-primary">立即发布</button>
</div>
</div>
</form>
{% endblock %}
question.html
{% extends 'base.html' %} {% block title %}注册{% endblock %} {% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/login_regist.css') }}">
{% endblock %} {% block main %}
<h3 class="page-title">注册</h3>
<form action="" method="POST">
<div class='form-container'>
<div class='form-group'>
<input type="text" class="form-control" placeholder="手机号码"
name="telephone">
</div>
<div class='form-group'>
<input type="text" class="form-control" placeholder="用户名"
name="username">
</div>
<div class='form-group'>
<input type="password" class="form-control" placeholder="密码"
name="password1">
</div>
<div class='form-group'>
<input type="password" class="form-control" placeholder="确认密码"
name="password2">
</div>
<div class="form-group">
<button class="btn btn-primary btn-block">立即注册</button>
</div>
</div>
</form> {% endblock %}
regist.html
4、css文件
.logo{
width: 30px;
} body{
background: #f3f3f3;
}
.main{
background: #fff;
width: 730px;
margin: 0 auto;
overflow: hidden;
padding: 10px;
} .page-title{
text-align: center;
}
static\css\base.css
.question-info{
text-align: center;
margin-top: 20px; } .answer-list{
padding-left:;
}
.answer-list li{
list-style: none;
border-bottom: 1px solid #eee;
padding-top: 10px;
} .avatar{
width: 40px;
height: 40px;
border-radius: 50%;
} user-info{
font-size: 16px;
color: #9b9b9b;
line-height: 40px;
} .user-info .username{
margin-left: 20px;
} .answer-content{
margin-left: 60px;
}
.user-info .create-time{
float: right;
}
static\css\detail.css
ul{
list-style: none;
padding-left:;
} ul li{
border-bottom: 1px solid #eee;
overflow: hidden;
}
.avatar-group{
width: 38px;
height: 100%;
float: left;
} .avatar-group .avatar{
width: 38px;
height: 38px;
} .question-group{
float: left;
width: 660px;
margin-left: 10px;
} .question-title a{
color: #259;
font-weight:;
} .question-info{
text-align: right;
} .question-info .question-author{
margin-right: 20px; }
static\css\index.css
.form-container{
width: 300px;
margin: 0 auto;
}
static\css\login_regist.css
.form-container
.form-container{
width: 500px;
margin: 0 auto;
text-align: right;
}
static\css\question.css
5、创建数据库表命令
python manage.py db init # 创建迁移的仓库
Python manage.py db migrate # 创建迁移的脚本
python manage.py db upgrade # 更新数据库
python manage.py runserver # 运行项目
1.2 效果展示
1、登录
2、登录
3、发布问答
02: flask 使用举例的更多相关文章
- 02 flask源码剖析之flask快速使用
02 flask快速使用 目录 02 flask快速使用 1.flask与django的区别 2. 安装 3. 依赖wsgi Werkzeug 4. 快速使用flask 5. 用户登录&用户管 ...
- 02 flask 请求钩子、异常捕获、上下文、Flask-Script 扩展、jinja2 模板引擎、csrf防范
一 请求勾子 在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如: 在请求开始时,建立数据库连接: 在请求开始时,根据需求进行权限校验: 在请求结束时,指定数据的交互格式: 为了让每个 ...
- Flask web开发 处理Ajax请求
本文介绍如何处理ajax请求, 一.处理ajax的post请求 举例一: js代码举例如下: var id = obj.parentNode.parentNode.id; $.post("/ ...
- 使用gunicorn部署Flask项目
[*] 本文出处:http://b1u3buf4.xyz/ [*] 本文作者:B1u3Buf4 [*] 本文授权:禁止转载 从自己的博客移动过来. gunicorn是一个python Wsgi的WEB ...
- Python-S9-Day116——Flask框架相关
01 内容回顾 02 Flask框架:路由和视图(一) 03 Flask框架:路由和视图(二) 04 Flask框架:路由和视图(三) 05 Flask框架:路由和视图(四) 06 Flask框架:s ...
- flask源码剖析系列(系列目录)
flask源码剖析系列(系列目录) 01 flask源码剖析之werkzurg 了解wsgi 02 flask源码剖析之flask快速使用 03 flask源码剖析之threading.local和高 ...
- 【shell】多命令执行顺序
:举例[root@andon ~]# date;dd if=/dev/zero of=/home/1 bs=1k count=10240;date ##统计dd命令消耗时间,其中/dev/zero为空 ...
- 《Python开发实战》
<Python开发实战> 基本信息 作者: (日)BePROUD股份有限公司 译者: 盛荣 丛书名: 图灵程序设计丛书 出版社:人民邮电出版社 ISBN:9787115320896 上架时 ...
- pip 常用命令小结
pip 常用命令小结 pip这个工具我们经常会用到,毕竟python 是一门以第三方库庞大而著名的编程语言,所以我们总会用pip 安装一些依赖库,当然这只是pip 最常用的一个命令,下面就来介绍一下 ...
随机推荐
- python的赋值,深拷贝和浅拷贝的区别
原文地址https://www.cnblogs.com/xueli/p/4952063.html 赋值:a = [1,2,3,["a","b"]] b=a,那 ...
- centos7挂载新加4T硬盘到/home目录
以下操作均在root环境下运行. 1.查看硬盘 # fdisk -l 发现硬盘为/dev/sdb 大小4T 2.如果此硬盘以前有过分区,则先对磁盘格式化: # mkfs -t ext4 /dev/sd ...
- js语法没有任何问题但是就是不走,检查js中命名的变量名,用 service-area错误,改service_area (原)
js语法没有任何问题但是就是不走,检查js中命名的变量名,用 service-area错误,改service_area
- sqoop往远程hdfs写入数据时出现Permission denied 的问题
猜测出现该问题的原因是sqoop工具用的是执行sqoop工具所用的本地用户名. 如果远程hdfs用的用户是hdfs,那么我本地还需要建一个名为hdfs的用户? 其实不需要,只要为用户增加一个环境变量就 ...
- 删除SQL Server大容量日志的方法(转)
删除SQL Server大容量日志的方法 亲自实践的方法 1.分享数据库,如果提示被其他连接占用,不能分离,刚勾上drop connections 2.复制下所有文件,一定要备份好,以防自己操作失误 ...
- PM2管理工具的使用
linux上PM2可以管理服务程序,防止程序无故关闭,具有程序守护功能,自动重启服务器程序,监控程序等好处,很方便,具体自己去体会! 官网地址: http://pm2.keymetrics.io/ ...
- 前端 dojo
http://dojotoolkit.org/documentation/tutorials/1.10/hello_dojo/ html在线编辑器 国内 http://runjs.cn 国外 http ...
- 城市里的间谍B901
城市里的间谍 城市里的间谍 难度级别:C: 运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 某城市的地铁是线性的,有 n(2 <= n ...
- mysql 问题:Unknown system variable 'query_cache_size'
报错:Unknown system variable 'query_cache_size' mysql 的 java 驱动等级比较低,与mysql 数据库不匹配.
- C语言学习感受
C语言,是我学习的第一种计算机语言,是他作为我编写程序的开始,在学习的时候,先学习了最基础的知识,在语言的理论学习语法上,我逐渐的了解了C语言并且对他有了基础的认识与理解,随着学习内容的不断深入,我逐 ...