flask 留言板(flask 39)

image.png

views.py

from flask import flash,render_template,redirect,url_for from app import app,db from models import Message from forms import HelloForm

@app.route('/',methods=['GET','POST']) def index(): messages=Message.query.order_by(Message.timestamp.desc()).all() form=HelloForm() if form.validate_on_submit(): name=form.name.data body=form.body.data message=Message(body=body,name=name) db.session.add(message) db.session.commit() flash('Your message have been sent to the world!') return redirect(url_for('index')) return render_template('index.html',form=form,messages=messages)

settings.py

import os import sys

from app import app

SQLite URI compatible

WIN = sys.platform.startswith('win') if WIN: prefix = 'sqlite:///' else: prefix = 'sqlite:////'

dev_db = prefix + os.path.join(os.path.dirname(app.root_path), 'data.db')

SECRET_KEY = os.getenv('SECRET_KEY', 'secret string') SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URI', dev_db)

models.py

from datetime import datetime from app import db

class Message(db.Model): id=db.Column(db.Integer,primary_key=True) body=db.Column(db.String(200)) name=db.Column(db.String(20)) timestamp=db.Column(db.DateTime,default=datetime.now,index=True)

forms.py

from flask_wtf import FlaskForm from wtforms import StringField,SubmitField,TextAreaField from wtforms.validators import DataRequired,Length

class HelloForm(FlaskForm): name=StringField("Name",validators=[DataRequired(message="name must be not empty"),Length(1,20)]) body=TextAreaField("Message",validators=[DataRequired(message="message must be not empty"),Length(1,200)]) submit=SubmitField()

errors.py

from flask import render_template from app import app

@app.errorhandler(404) def page_not_found(e): return render_template('errors/404.html'), 404

@app.errorhandler(500) def internal_server_error(e): return render_template('errors/500.html'), 500

commands.py

from app import db,manager from faker import Faker from models import Message

@manager.command def hell(): print("hello")

@manager.option('-c','--count',dest='count',default=20,help='Quantity of messages,default is 20.') def forge(count): db.drop_all() db.create_all()

faker=Faker()
print('Working...')

for i in range(int(count)):
    message=Message(name=faker.name(),body=faker.sentence(),
                    timestamp=faker.date_time_this_year())
    db.session.add(message)
db.session.commit()
print('Create %d fake messages' % int(count))

app.py

from flask import Flask from flask_bootstrap import Bootstrap from flask_moment import Moment from flask_sqlalchemy import SQLAlchemy from flask_script import Manager

app = Flask('sayhello') app.config.from_pyfile('settings.py') app.jinja_env.trim_blocks = True app.jinja_env.lstrip_blocks = True

db = SQLAlchemy(app) bootstrap = Bootstrap(app) moment = Moment(app) manager=Manager(app)

import views, errors from commands import *

if name == 'main': manager.run()

.flaskenv

FLASK_APP=sayhello FLASK_ENV=development

templates/index.html

{% extends "base.html" %} {% from 'bootstrap/form.html' import render_form %} {% block content %} <div class="hello-form"> {{ render_form(form,action=request.full_path) }} </div> <h5>{{ messages|length }} messages <small class="float-right"> <a href="#bottom" title="Go Bottom">↓</a> </small> </h5> <div class="list-group"> {% for message in messages %} <a class="list-group-item list-group-item-action flex-column"> <div class="d-flex w-100 justify-content-between"> <h5 class="mb-1 text-success">{{ message.name }} <small class="text-muted"> #{{ loop.revindex }}</small> </h5> <small data-toggle="tooltip" data-placement="top" data-timestamp="{{ message.timestamp.strftime('%Y-%m-%dT%H:%M:%SZ') }}" data-delay="500"> {{ moment(message.timestamp).fromNow(refresh=True) }} </small> </div> <p class="mb-1">{{ message.body }}</p> </a> {% endfor %} </div> {% endblock %}

templates/base.html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>{% block title %}Say Hello!{% endblock %}</title> <link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}" type="text/css"> </head> <body> <main class="container"> <header> <h1 class="text-center display-4"> <a href="{{ url_for('index') }}" class="text-success"><strong>Say Hello</strong></a> <small class="text-muted sub-title">to the world</small> </h1> </header> {% for message in get_flashed_messages() %} <div class="alert alert-info"> <button type="button" class="close" data-dismiss="alert">×</button> {{ message }} </div> {% endfor %} {% block content %}{% endblock %} <footer class="text-center"> {% block footer %} <small> © 2018 <a href="xxxxxxxxxx" title="xxxxxxxx">xxx</a> / <a href="xxxxxxxxxxxxxxx" title="xxxxxxx">xxx</a> / <a href="xxxxxxxx" title="xxxx">xxx</a> </small> <p><a id="bottom" href="#" title="Go Top">↑</a></p> {% endblock %} </footer> </main> <script type="text/javascript" src="{{ url_for('static', filename='js/jquery-3.2.1.slim.min.js') }}"></script> <script type="text/javascript" src="{{ url_for('static', filename='js/popper.min.js') }}"></script> <script type="text/javascript" src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script> <script type="text/javascript" src="{{ url_for('static', filename='js/script.js') }}"></script> {{ moment.include_moment(local_js=url_for('static', filename='js/moment-with-locales.min.js')) }} </body> </html>

tempates/errors/404.html

{% extends "base.html" %}

{% block title %}404 Error{% endblock %}

{% block content %} <p class="text-center">Page Not Found</p> {% endblock %}

{% block footer %} <a href="{{ url_for('index') }}">← Go Back</a> {% endblock %}

templates/errors/500.html

{% extends "base.html" %}

{% block title %}500 Error{% endblock %}

{% block content %} <p class="text-center">Internal Server Error</p> {% endblock %}

{% block footer %} <a href="{{ url_for('index') }}">← Go Back</a> {% endblock %}

static

image.png

bootstrap 版本为4

转载自:https://github.com/greyli

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏EffectiveCoding

Go 语言基础--错误&异常浅析

如果go是你的第一门语言,go的异常和错误体系可能比较容易接受,但如果你有一定的Java或者c++基础,go的异常和错误体系可能会比较不适应。 go的错误及异...

7920
来自专栏AI研习社

程序员必读经典长文:用十年时间自学编程

AI开发者按:相信很多做技术的同学都自学过,也看过「Teach Yourself Programming in Ten Years」这篇文章。虽然离初次发表已经...

9320
来自专栏点云PCL

PCL中多个可视化窗口

viewer->createViewPort(double Xmin,double Ymin,double Xmax,double Ymax)

35610
来自专栏EffectiveCoding

Go 语言基础--map 浅析

map通常是一种无序键值对的集合,map存在的意义主要是利用map的结构根据key来快速检索数据,在go中也是这样的。 map 也是一种集合,我们可以像遍历数...

5020
来自专栏Pulsar-V

VV的操作系统笔记(二)保护模式及GDT、LDT

通过执行g++ -c test.cpp以后生成obj文件,然后通过objdump -d test.o输出编译后的指令得到

9630
来自专栏跟Qt君学编程

Windows编译libjpeg库

  由于VC++6的编译方法与VS2017方法基本相同,这里使用VS2017的编译环境编译。

28710
来自专栏EffectiveCoding

Java Concurrent 内部类基础介绍

看Concurrent包源码时,其中存在大量的内部类使用,所以特地抽出一篇来介绍内部类。内部类其实是Java 经常用到的一个小的知识点。

4120
来自专栏程序员成长指北

Node进阶-探究不在V8堆内存中存储的Buffer对象

## 前言 写完上一篇文章想学Node.js,stream先有必要搞清楚留下了悬念, stream对象数据流转的具体内容是什么?本篇文章将为大家进行深入讲解。

8620
来自专栏Python绿色通道

PythonWeb | 搭建单服务实现多域名访问

最近使用Django开发一个小程序和后台管理系统 ,需要将这两个不同的项目部署到同一个服务里面,然后使用不同的域名来访问不同的项目。Django默认的只支持单服...

18410
来自专栏EffectiveCoding

Java Concurrent Atomic实现原理&源码解读(JDK 10)

JDK 10,可以说是很新了,比起JDK 8更新了不少实现,比如说下面会讲到VarHandle

9820

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励