发布功能完成。

  • 编写要求登录的装饰器

from functools import wraps

def loginFirst(func): #参数是函数

@wraps(func)

      def wrapper(*args, ** kwargs): #定义个函数将其返回

          #要求登录

          return func(*args, ** kwargs)

      return wrapper #返回一个函数

  • 应用装饰器,要求在发布前进行登录,登录后可发布。
@app.route('/question/',methods=['GET','POST'])
@loginFirst
def question():

 

  • 建立发布内容的对象关系映射。
class Question(db.Model):
  • 完成发布函数。

保存到数据库。

重定向到首页。

 

py文件:

from flask import Flask, render_template, request, redirect, url_for, session
from flask_sqlalchemy import SQLAlchemy
import config
from functools import wraps
from datetime import datetime

app = Flask(__name__)  # 创建Flask对象
app.config.from_object(config)  # 关联config.py文件进来
db = SQLAlchemy(app)  # 建立和数据库的关系映射


class User(db.Model):  # 创建类User
    __tablename__ = 'user'  # 类对应的表名user
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)  # autoincrement自增长
    username = db.Column(db.String(20), nullable=False)  # nullable是否为空
    password = db.Column(db.String(20), nullable=False)
    nickname = db.Column(db.String(20), nullable=True)


class Fabu(db.Model):
    __tablename__ = 'fabu'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(100), nullable=False)
    detail = db.Column(db.Text, nullable=False)
    creat_time = db.Column(db.DateTime, default=datetime.now)   # 提交时间会自己赋值
    author_id = db.Column(db.Integer, db.ForeignKey('user.id'))   # 数据类型是db.Integer,db.ForeignKey参数指定外键是哪个表中哪个id
    author = db.relationship('User', backref=db.backref('fabu'))   # 建立关联,其author属性将返回与问答相关联的用户实例,相当于数据库中的表连接
    # 第一个参数表明这个关系的另一端是哪个类,第二个参数backref,将向类中添加一个fabu属性,从而定义反向关系,这一属性可访问Fabu类,获取的是模型对象

db.create_all()  # 测试是否连接成功

'''
# 插入功能
user = User(username='15',password='12')
db.session.add(user)
db.session.commit()

# 查询功能
user=User.query.filter(User.username=="15").first()
print(user.username,user.password)

# 修改功能
user=User.query.filter(User.username=="15").first()
user.password='888'
db.session.commit()

# 删除功能
user=User.query.filter(User.username=="15").first()
db.session.delete(user)
db.session.commit()
'''


# session会话连接
# filter()过滤器
# route制定路径和函数之间的关系
# def定义一个变量

@app.route('/')  # 跳转首页。
def daohang():
    return render_template('daohang.html')


@app.route('/lin/')  # 跳转测试。
def lin():
    return 'lin'


# 跳转登陆。
@app.route('/denglu/', methods=['GET', 'POST'])  # methods定义它有两种请求方式
def denglu():
    if request.method == 'GET':
        return render_template('denglu.html')
    else:
        username = request.form.get('user')  # post请求模式,安排对象接收数据
        password = request.form.get('pass')
        user = User.query.filter(User.username == username).first()  # 作查询,并判断
        if user:  # 判断用户名
            session['user'] = username  # 利用session添加传回来的值username
            session.permanent = True  # 设置session过期的时间
            if user.password == password:  # 判断密码
                return redirect(url_for('daohang'))
            else:
                return u'用户密码错误'
        else:
            return u'用户不存在,请先注册'


@app.context_processor  # 上下文处理器,定义变量然后在所有模板中都可以调用,类似idea中的model
def mycontext():
    user = session.get('user')
    if user:
        return {'username': user}   # 包装到username,在所有html模板中可调用
    else:
        return {}  # 返回空字典,因为返回结果必须是dict


# 跳转注销。
@app.route('/logout')
def logout():
    session.clear()
    return redirect(url_for('daohang'))


# 跳转注册。
@app.route('/zhuce/', methods=['GET', 'POST'])  # methods定义它有两种请求方式,因为它在表单的请求是post,类似我们在idea中的sava请求模式
def zhuce():
    if request.method == 'GET':
        return render_template('zhuce.html')
    else:
        username = request.form.get('user')  # post请求模式,安排对象接收数据
        password = request.form.get('pass')
        nickname = request.form.get('nickname')
        user = User.query.filter(User.username == username).first()  # 作查询,并判断
        if user:
            return u'该用户已存在'
        else:
            user = User(username=username, password=password, nickname=nickname)  # 将对象接收的数据赋到User类中,即存到数据库
            db.session.add(user)  # 执行操作
            db.session.commit()
            return redirect(url_for('denglu'))  # redirect重定向


# 定义decorator可以增强函数功能,装饰器本身是函数,入参是函数,返回值也是函数
def loginFirst(fabu):
    @wraps(fabu)   #加上wraps,它可以保留原有函数的__name__,docstring
    def wrapper(*args, **kwargs):   #定义wrapper函数将其返回,用*args, **kwargs把原函数的参数进行传递
        if session.get('user'):
            return fabu(*args, **kwargs)
        else:
            return redirect(url_for('denglu'))
    return wrapper


# 跳转图片。
@app.route('/tupian/')
def tupian():
    return render_template('tupian.html')


# 跳转发布。
@app.route('/fabu/', methods=['GET', 'POST'])   # methods定义它有两种请求方式
@loginFirst   #将decorator定义的增强函数放在待增强函数定义的上面
def fabu():
    if request.method == 'GET':
        return render_template('fabu.html')
    else:
        title = request.form.get('title')   # post请求模式,安排对象接收数据
        detail = request.form.get('detail')
        author_id=User.query.filter(User.username == session.get('user')).first().id   #将session get到的user进行查询并取出id放到外键author_id中
        fabu=Fabu(title=title,detail=detail,author_id=author_id)   # 将对象接收的数据赋到Fabu类中,即存到数据库
        db.session.add(fabu)  # 执行操作
        db.session.commit()   # 提交到数据库
        return redirect(url_for('daohang'))  # redirect重定向



if __name__ == '__main__':
    app.run(debug=True)

fabu.html:

{% extends 'daohang.html' %}
{% block fabutitle %}发布{% endblock %}
{% block fabuhead %}
    <link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script>
{% endblock %}
{% block fabubody %}
    <form role="form" action="{{ url_for('fabu') }}" method="post">
        <div class="form-group">
            <label for="name">选择列表</label>
            <select class="form-control">
                <option>1</option>
                <option>2</option>
                <option>3</option>
                <option>4</option>
                <option>5</option>
            </select>
            <label for="title">标题</label>
            <textarea class="form-control" rows="1" id="title" name="title"></textarea>
            <label for="detail">详情</label>
            <textarea class="form-control" rows="5" id="detail" name="detail"></textarea>
            <input type="checkbox" name="c1" id="c1" value="">记住我
            <br>
            <div id=""><br></div>
            <input type="submit" value="发布" class="btn btn-default" onclick="">
        </div>
    </form>
{% endblock %}

 

posted on 2017-11-28 12:10  L文斌  阅读(179)  评论(0编辑  收藏  举报