Flask留言板Demo

初学Python,用flask框架写了一个留言板,分享出来供大家观赏,希望对大家有帮助

环境搭建

  • pycharm
  • python2.7
  • Navicat
  • mysql

基础知识

  • python
  • html

依赖模块

  • flask
  • jinja2
  • bootstrap
  • flask-login
  • flask-mysql
  • SQLAlchemy
  • Flask-script

留言板功能

  • 登录/注册
  • 注销
  • 留言
  • 会话保持(利用flask-login)

程序架构

/messageboard
    /bbs                  #留言
        /__init__.py
        /form.py
        /views.py
    /reglogin             #登录注册
        /__init__.py
        /form.py
        /views.py
    /static               #静态文件
    /templates            #模板
        /base.html
        /index.html
        /login.html
        /register.html
    __init__.py
    model.py              #数据库
/manage.py                #脚本
/run.py                   #主程序

留言板的实现,主要利用MVC架构,显得程序层次感比较分明

数据库 model.py

留言板的实现,数据库必不可少,一来存储用户信息(用户名和密码),二来存储用户的留言信息

# coding=utf-8
from . import db
from . import login_manager
from datetime import datetime
from flask_login import UserMixin


#用户类
class User(db.Model, UserMixin):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(80), unique=True)
    password = db.Column(db.String(32))
    salt = db.Column(db.String(32))

    #用户和留言连接,一个用户会有多个留言
    message = db.relationship('Message', backref='user', lazy='dynamic')

    __table_args__ = {
        'mysql_charset': 'utf8'
    }


    def __init__(self, username, password, salt=''):
        self.username = username
        self.password = password
        self.salt = salt

    def __repr__(self):
        return ('' % (self.id, self.username))


#留言类
class Message(db.Model):
    __tablename__= 'message'
    id = db.Column(db.Integer, primary_key=True)
    #外键
    author_id = db.Column(db.Integer,db.ForeignKey('user.id'))
    msg = db.Column(db.String(1024))
    timestamp = db.Column(db.DateTime, default=datetime.utcnow)

    __table_args__ = {
        'mysql_charset': 'utf8'
    }

    def __init__(self, author_id, msg, timestamp):
        self.author_id = author_id
        self.msg = msg
        self.timestamp = timestamp

    def __repr__(self):
        return ('' % (self.id, self.msg))


#login_manager 返回用户对象,回调,无效返回None
@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

初始配置 init.py

# -*- encoding=UTF-8 -*-
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_bootstrap import Bootstrap

app = None
#db实例化
db = SQLAlchemy(use_native_unicode='utf8')
bootstrap = Bootstrap()
#login-manager处理登入,会话管理,管理长时间记住用户的会话
login_manager = LoginManager()
login_manager.session_protection = 'strong'
# login_view设置登陆页面的端点
login_manager.login_view = 'reglogin.login'

#导入import模块
import sys
reload(sys)
sys.setdefaultencoding("utf-8")

def create_app():
    global app
    # app配置数据库
    app = Flask(__name__, template_folder='templates')
    app.config['SQLALCHEMY_DATABASE_URI'] = '******'  # 配置数据库,数据库的库名和密码,自己补上
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
    #secret_key
    app.config['SECRET_KEY'] = 'MONKEY'

    # db初始化
    db.init_app(app)
    bootstrap.init_app(app)
    login_manager.init_app(app)

    # 引入视图和model
    from .reglogin import reglogin_view as login_blueprint
    from .bbs import bbs_view as bbs_blueprint

    # app加载登录注册蓝图
    app.register_blueprint(login_blueprint)
    # app加载留言板蓝图
    app.register_blueprint(bbs_blueprint)

    return app

脚本启动 manage.py

#-*- encoding=UTF-8 -*-

from flask_script import Manager
from messageboard import db
from messageboard import create_app

app = create_app()
manager = Manager(app)

@manager.command
def init_database():
    db.drop_all()
    db.create_all()

if __name__ == '__main__':
    manager.run()

使用以下命令,完成数据库的创建

python manage.py init_database 

程序启动 run.py

#-*- encoding=UTF-8 -*-
from messageboard import create_app

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

登录注册 relogin

登录注册的init.py
# __init__.py
# coding=utf-8
from flask import Blueprint
reglogin_view = Blueprint('reglogin_view', __name__)
from messageboard.reglogin import views
登录注册的表单 form.py
# -*- coding:utf-8 -*-
from flask_wtf import FlaskForm
from wtforms.fields import simple
from wtforms import validators
from wtforms import widgets
from wtforms import SubmitField, BooleanField


#登陆表单
class LoginForm(FlaskForm):
    username = simple.StringField(
        label='用户名',
        validators=[
            validators.DataRequired(message='用户名不能为空.'),
        ],
        widget=widgets.TextInput(),
        render_kw={'class': 'form-control'}
    )
    password = simple.PasswordField(
        label='密码',
        validators=[
            validators.DataRequired(message='密码不能为空.'),
            validators.Length(min=8, message='密码长度必须大于%(min)d'),
        ],
        widget=widgets.PasswordInput(),
        render_kw={'class': 'form-control'}
    )
    remember_me = BooleanField(label=u'记住我', id='loginlength')
    login = SubmitField(label=u'登录' )


#注册表单
class RegisterForm(FlaskForm):
    username = simple.StringField(
        label='用户名',
        validators=[
            validators.DataRequired(message='用户名不能为空.'),
        ],
        widget=widgets.TextInput(),
        render_kw={'class': 'form-control'},
        default='alex'
    )
    password = simple.PasswordField(
        label=u'密码',
        validators=[
            validators.DataRequired(message='密码不能为空.'),
            validators.Length(min=8, message='密码长度必须大于%(min)d'),
        ],
        widget=widgets.PasswordInput(),
        render_kw={'class': 'form-control'}
    )
    password_confirm = simple.PasswordField(
        label=u'确认密码',
        validators=[
            validators.DataRequired(message='确认密码不能为空'),
            validators.EqualTo('password',message="两次密码输入不一致")
        ],
        widget = widgets.PasswordInput(),
        render_kw = {'class': 'form-control'}
    )
    submit = SubmitField(label=u'马上注册')
登录注册的 views.py
  • 注册新用户时,密码需要加密,本文使用md5+salt的方式对密码加密
  • 登录注册时,都会提交表单form,当form提交验证正确时,会进行登录注册下一步功能
# coding=utf-8
from . import reglogin_view
from ..models import User, db
import hashlib
import random
from flask import render_template, redirect, request, flash, url_for
from flask_login import login_user, logout_user, login_required
from form import LoginForm, RegisterForm


# 登录页
@reglogin_view.route('/login/', methods={'get', 'post'})
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user is not None:
            # 密码正确验证
            m = hashlib.md5()
            m.update(form.password.data + user.salt)
            print
            if m.hexdigest() != user.password:
                flash('密码输入错误')
                return redirect('/login')
            login_user(user)
            flash('登录成功')
            return redirect('/')
        else:
            flash('用户或密码错误')

    return render_template('login.html', form=form)


# 注册页
@reglogin_view.route('/register/', methods={'get', 'post'})
def register():
    form = RegisterForm(request.form)
    if request.method == 'POST':
        if form.validate_on_submit():
            # 查看用户是否存在数据库中
            user = User.query.filter_by(username=form.username.data).first()
            if user is not None:
                flash('用户名已经存在')
                return redirect('/register')
            # 用户名不存在,进而注册
            # 密码加md5+盐
            salt = ''.join(random.sample('0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 10))
            m = hashlib.md5()
            m.update(form.password.data + salt)
            password = m.hexdigest()
            # 新用户提交入库
            user = User(form.username.data, password, salt)
            # 数据库提交
            db.session.add(user)
            db.session.commit()
            flash('注册成功')
            return redirect(url_for('reglogin_view.login'))

    return render_template('register.html', form=form)


# 登出页
@reglogin_view.route('/logout/')
@login_required
def logout():
    logout_user()
    flash('你已退出登录')
    return redirect(url_for('reglogin_view.login'))

留言 bbs

bbs的init.py
# coding=utf-8
from flask import Blueprint
bbs_view = Blueprint('bbs_view', __name__)
from messageboard.bbs import views
bbs的form.py
# -*- coding:utf-8 -*-
from flask_wtf import FlaskForm
from wtforms.fields import simple
from wtforms import validators
from wtforms import widgets
from wtforms import SubmitField

# 留言板表单
class MessageForm(FlaskForm):
    msg = simple.TextAreaField(
        label='输入留言',
        validators=[
            validators.DataRequired(),
        ],
    )
    submit = SubmitField(label=u'提交留言' )
bbs的views.py

这里主要实现了主页的功能,主页上能够看到历史留言,当然留言必须登录之后才行

# coding=utf-8
from . import bbs_view
from flask import render_template, redirect, request, flash, url_for
from form import MessageForm
from flask_login import current_user
from messageboard.models import Message,db
import datetime


# 主页
@bbs_view.route('/', methods={'get', 'post'})
def index():
    form = MessageForm()
    if form.validate_on_submit():
        if current_user.is_authenticated:
            nowTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            message = Message(current_user.id, form.msg.data, nowTime)
            db.session.add(message)
            db.session.commit()
            flash('留言成功')
            redirect('/')
        else:
            flash('留言失败,请登录账号后进行留言')
            redirect('/')
    messages = Message.query.order_by(Message.timestamp.desc()).all()
    return render_template('index.html', form=form, messages=messages)

以上便是留言板的python源码,那么html的源码在哪呢,别急,下面就是。

templates 模板

本项目的留言板界面,主要继承bootstrap/base.html模板

base.html
{% extends "bootstrap/base.html" %}
{% block title %}留言板{% endblock %}
{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
    <div class="container">
        <div class="navbar-header">
            <a class="navbar-brand" href="/">留言板a>
        div>
        <div class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
                <li><a href="/">主页a>li>
            ul>
            <ul class="nav navbar-nav navbar-right">
                {% if current_user.is_authenticated %}
                <li><a href="{{ url_for('reglogin_view.logout') }}">注销a>li>
                {% else %}
                <li><a href="{{ url_for('reglogin_view.login') }}">登录a>li>
                <li><a href="{{ url_for('reglogin_view.register') }}">注册a>li>
                {% endif %}
            ul>
        div>
    div>
div>
{% endblock %}
index.html

index为主页,主页上有滑动显示的留言

{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block title %}首页{% endblock %}

{% block content %}
    <div class="page-header">
        <div class="container">
            <h1>
                欢迎进入留言板,
                {% if current_user.is_authenticated %}
                {{current_user.username}}
                {% else %}
                陌生人
                {% endif %}
            h1>
        div>
        <div class="container">
            <h3>
                {% for message in get_flashed_messages() %}
                {{ message }}
                {% endfor %}
            h3>
        div>
    div>

    <div class="container">
        <form method="post" id="bbsform" accept-charset="utf-8" onsubmit="document.charset='utf-8'">
            {{ wtf.quick_form(form) }}
        form>
    div>

    <div class="container">
        <ul class="Message">
            <h4>
            {% for message in messages%}
                <li>
                    <div>
                        {{message.user.username}}    {{message.timestamp}}
                    div>
                    <div>
                        {{message.msg}}
                    div>
                li>
                {% endfor %}
            h4>
        ul>
    div>>
{% endblock %}
login.html
{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block title %}登录{% endblock %}
{% block content %}
    <div class="page-header">
        <div class="container">
            <h1>登录h1>
        div>
        <div class="container">
            <h3>
                {% for message in get_flashed_messages() %}
                {{ message }}
                {% endfor %}
            h3>
        div>
    div>
    <div class="container">
        <form method="post" id="loginform">
            {{ wtf.quick_form(form) }}
        form>
    div>
{% endblock %}
register.html
{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block title %}注册{% endblock %}
{% block content %}
    <div class="page-header">
        <div class="container">
            <h1>注册h1>
        div>
        <div class="container">
            <h3>
                {% for message in get_flashed_messages() %}
                {{ message }}
                {% endfor %}
            h3>
        div>
    div>
    <div class="container">
        <form method="post">
            {{ wtf.quick_form(form) }}
        form>
    div>
{% endblock %}

效果图

主页

Flask留言板Demo_第1张图片

登录页

Flask留言板Demo_第2张图片

注册页

Flask留言板Demo_第3张图片

登录成功后页面

这里注册了一个hello账户,登录成功后,欢迎页面会变样子
Flask留言板Demo_第4张图片

留言

Flask留言板Demo_第5张图片

至此,一个简单的留言板就开发完成,希望各位大佬多多指导!

源码下载链接

https://download.csdn.net/download/pupoqian3720/10574857

参考

Flask官网:http://flask.pocoo.org/
Flask-SQLAlchemy官网:http://www.pythondoc.com/flask-sqlalchemy/quickstart.html

你可能感兴趣的:(Python,web)