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 使用举例的更多相关文章

  1. 02 flask源码剖析之flask快速使用

    02 flask快速使用 目录 02 flask快速使用 1.flask与django的区别 2. 安装 3. 依赖wsgi Werkzeug 4. 快速使用flask 5. 用户登录&用户管 ...

  2. 02 flask 请求钩子、异常捕获、上下文、Flask-Script 扩展、jinja2 模板引擎、csrf防范

    一 请求勾子 在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如: 在请求开始时,建立数据库连接: 在请求开始时,根据需求进行权限校验: 在请求结束时,指定数据的交互格式: 为了让每个 ...

  3. Flask web开发 处理Ajax请求

    本文介绍如何处理ajax请求, 一.处理ajax的post请求 举例一: js代码举例如下: var id = obj.parentNode.parentNode.id; $.post("/ ...

  4. 使用gunicorn部署Flask项目

    [*] 本文出处:http://b1u3buf4.xyz/ [*] 本文作者:B1u3Buf4 [*] 本文授权:禁止转载 从自己的博客移动过来. gunicorn是一个python Wsgi的WEB ...

  5. Python-S9-Day116——Flask框架相关

    01 内容回顾 02 Flask框架:路由和视图(一) 03 Flask框架:路由和视图(二) 04 Flask框架:路由和视图(三) 05 Flask框架:路由和视图(四) 06 Flask框架:s ...

  6. flask源码剖析系列(系列目录)

    flask源码剖析系列(系列目录) 01 flask源码剖析之werkzurg 了解wsgi 02 flask源码剖析之flask快速使用 03 flask源码剖析之threading.local和高 ...

  7. 【shell】多命令执行顺序

    :举例[root@andon ~]# date;dd if=/dev/zero of=/home/1 bs=1k count=10240;date ##统计dd命令消耗时间,其中/dev/zero为空 ...

  8. 《Python开发实战》

    <Python开发实战> 基本信息 作者: (日)BePROUD股份有限公司 译者: 盛荣 丛书名: 图灵程序设计丛书 出版社:人民邮电出版社 ISBN:9787115320896 上架时 ...

  9. pip 常用命令小结

    pip 常用命令小结 pip这个工具我们经常会用到,毕竟python 是一门以第三方库庞大而著名的编程语言,所以我们总会用pip 安装一些依赖库,当然这只是pip 最常用的一个命令,下面就来介绍一下 ...

随机推荐

  1. maven 详解二

    转自 http://www.cnblogs.com/whgk/p/7121336.html 前一节我们明白了maven是个什么玩意,这一节就来讲讲他的一个重要的应用场景,也就是通过maven将一个ss ...

  2. HDU 3117 Fibonacci Numbers(矩阵)

    Fibonacci Numbers [题目链接]Fibonacci Numbers [题目类型]矩阵 &题解: 后4位是矩阵快速幂求,前4位是用log加Fibonacci通项公式求,详见上一篇 ...

  3. css属性 background

    background 在一个声明中设置所有的背景属性. background-attachment 设置背景图像是否固定或者随着页面的其余部分滚动. background-color 设置元素的背景颜 ...

  4. c#之字符串,列表,接口,队列,栈,多态

    1.字符串的用法 using System; using System.Collections.Generic; using System.Linq; using System.Text; using ...

  5. 关于hibernate一级缓冲和二级缓冲

    关于一级缓冲和二级缓冲的内容,在面试的时候被问起来了,回答的不是很满意,所以有专门找了些有关这方面的文章加以理解 出自:http://blog.csdn.net/zdp072/article/deta ...

  6. Php 通过curl提交post内容为 Json的请求

    <?php $data = array("cNos" => array("1064917432615","1064917432615&qu ...

  7. caffe编译环境的错误:..build_release/src/caffe/proto/caffe.pb.h:23:35: fatal error: google/protobuf/arena.h: 没有那个文件

    在搭建caffe的环境时出现错误: .build_release/src/caffe/proto/caffe.pb.h:23:35: fatal error: google/protobuf/aren ...

  8. hdu5293 lca+dp+树状数组+时间戳

    题意是给了 n 个点的树,会有m条链条 链接两个点,计算出他们没有公共点的最大价值,  公共点时这样计算的只要在他们 lca 这条链上有公共点的就说明他们相交 dp[i]为这个点包含的子树所能得到的最 ...

  9. session_start 统计实时访客人数

    void Session_Start(object sender, EventArgs e) { Application.Lock(); Application["OnLine"] ...

  10. 【Hive学习之六】Hive Lateral View &视图&索引

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 apache-hive-3.1.1 ...