25-----BBS论坛
BBS论坛(二十五)
25.1.发布帖子后台逻辑完成
(1)apps/models.py
class PostModel(db.Model):
__tablename__ = 'post'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(200), nullable=False)
content = db.Column(db.Text, nullable=False)
create_time = db.Column(db.DateTime, default=datetime.now)
board_id = db.Column(db.Integer, db.ForeignKey('board.id'))
board = db.relationship('BoardModel', backref='posts')
(2)front/decorater.py
from flask import session,redirect,url_for
from functools import wraps
import config def login_requried(func):
@wraps(func)
def wrapper(*args,**kwargs):
if config.FRONT_USER_ID in session:
return func(*args,**kwargs)
else:
return redirect(url_for('front.signin'))
return wrapper
(3)front/forms.py
class AddPostForm(BaseForm):
title=StringField(validators=[InputRequired(message='请输入标题')])
content=StringField(validators=[InputRequired(message='请输入内容')])
board_id=IntegerField(validators=[InputRequired(message='请选择版块')])
(4)front/views.py
@bp.route('/apost/', methods=['POST', 'GET'])
@login_requried
def apost():
if request.method == 'GET':
boards = BoardModel.query.all()
return render_template('front/front_apost.html', boards=boards)
else:
form = AddPostForm(request.form)
if form.validate():
title = form.title.data
content = form.content.data
board_id = form.board_id.data
board = BoardModel.query.get(board_id)
if not board:
return restful.params_error(message='没有这个版块')
post = PostModel(title=title, content=content, board_id=board_id)
post.board = board
db.session.add(post)
db.session.commit()
return restful.success()
else:
return restful.params_error(message=form.get_error())
25.2.发布帖子界面布局完成
(1)把ueditor静态文件放到static目录下
(2)apps目录下新建ueditor目录
init.py
from .ueditor import bp
ueditor.py
#encoding: utf-8 from flask import (
Blueprint,
request,
jsonify,
url_for,
send_from_directory,
current_app as app
)
import json
import re
import string
import time
import hashlib
import random
import base64
import sys
import os
from urllib import parse
# 更改工作目录。这么做的目的是七牛qiniu的sdk
# 在设置缓存路径的时候默认会设置到C:/Windows/System32下面
# 会造成没有权限创建。
os.chdir(os.path.abspath(sys.path[0]))
try:
import qiniu
except:
pass
from io import BytesIO bp = Blueprint('ueditor',__name__,url_prefix='/ueditor') UEDITOR_UPLOAD_PATH = ""
UEDITOR_UPLOAD_TO_QINIU = False
UEDITOR_QINIU_ACCESS_KEY = ""
UEDITOR_QINIU_SECRET_KEY = ""
UEDITOR_QINIU_BUCKET_NAME = ""
UEDITOR_QINIU_DOMAIN = "" @bp.before_app_first_request
def before_first_request():
global UEDITOR_UPLOAD_PATH
global UEDITOR_UPLOAD_TO_QINIU
global UEDITOR_QINIU_ACCESS_KEY
global UEDITOR_QINIU_SECRET_KEY
global UEDITOR_QINIU_BUCKET_NAME
global UEDITOR_QINIU_DOMAIN
UEDITOR_UPLOAD_PATH = app.config.get('UEDITOR_UPLOAD_PATH')
if UEDITOR_UPLOAD_PATH and not os.path.exists(UEDITOR_UPLOAD_PATH):
os.mkdir(UEDITOR_UPLOAD_PATH) UEDITOR_UPLOAD_TO_QINIU = app.config.get("UEDITOR_UPLOAD_TO_QINIU")
if UEDITOR_UPLOAD_TO_QINIU:
try:
UEDITOR_QINIU_ACCESS_KEY = app.config["UEDITOR_QINIU_ACCESS_KEY"]
UEDITOR_QINIU_SECRET_KEY = app.config["UEDITOR_QINIU_SECRET_KEY"]
UEDITOR_QINIU_BUCKET_NAME = app.config["UEDITOR_QINIU_BUCKET_NAME"]
UEDITOR_QINIU_DOMAIN = app.config["UEDITOR_QINIU_DOMAIN"]
except Exception as e:
option = e.args[0]
raise RuntimeError('请在app.config中配置%s!'%option) csrf = app.extensions.get('csrf')
if csrf:
csrf.exempt(upload) def _random_filename(rawfilename):
letters = string.ascii_letters
random_filename = str(time.time()) + "".join(random.sample(letters,5))
filename = hashlib.md5(random_filename.encode('utf-8')).hexdigest()
subffix = os.path.splitext(rawfilename)[-1]
return filename + subffix @bp.route('/upload/',methods=['GET','POST'])
def upload():
action = request.args.get('action')
result = {}
if action == 'config':
config_path = os.path.join(bp.static_folder or app.static_folder,'ueditor','config.json')
with open(config_path,'r',encoding='utf-8') as fp:
result = json.loads(re.sub(r'\/\*.*\*\/','',fp.read())) elif action in ['uploadimage','uploadvideo','uploadfile']:
image = request.files.get("upfile")
filename = image.filename
save_filename = _random_filename(filename)
result = {
'state': '',
'url': '',
'title': '',
'original': ''
}
if UEDITOR_UPLOAD_TO_QINIU:
if not sys.modules.get('qiniu'):
raise RuntimeError('没有导入qiniu模块!')
buffer = BytesIO()
image.save(buffer)
buffer.seek(0)
q = qiniu.Auth(UEDITOR_QINIU_ACCESS_KEY, UEDITOR_QINIU_SECRET_KEY)
token = q.upload_token(UEDITOR_QINIU_BUCKET_NAME)
ret,info = qiniu.put_data(token,save_filename,buffer.read())
if info.ok:
result['state'] = "SUCCESS"
result['url'] = parse.urljoin(UEDITOR_QINIU_DOMAIN,ret['key'])
result['title'] = ret['key']
result['original'] = ret['key']
else:
image.save(os.path.join(UEDITOR_UPLOAD_PATH, save_filename))
result['state'] = "SUCCESS"
result['url'] = url_for('ueditor.files',filename=save_filename)
result['title'] = save_filename,
result['original'] = image.filename elif action == 'uploadscrawl':
base64data = request.form.get("upfile")
img = base64.b64decode(base64data)
filename = _random_filename('xx.png')
filepath = os.path.join(UEDITOR_UPLOAD_PATH,filename)
with open(filepath,'wb') as fp:
fp.write(img)
result = {
"state": "SUCCESS",
"url": url_for('files',filename=filename),
"title": filename,
"original": filename
}
return jsonify(result) @bp.route('/files/<filename>/')
def files(filename):
return send_from_directory(UEDITOR_UPLOAD_PATH,filename)
(3)perfect_bbs.py
from apps.ueditor import bp as ueditor_bp app.register_blueprint(ueditor_bp)
(4)front/index.html
<a class="btn btn-warning btn-block" href="{{ url_for('front.apost') }}" id="add-post-btn">发布帖子</a>
(5)front/apost.html
{% extends 'front/front_base.html' %}
{% from 'common/_macros.html' import static %} {% block title %}
发布帖子
{% endblock %} {% block head %}
<script src="{{ static('ueditor/ueditor.config.js') }}"></script>
<script src="{{ static('ueditor/ueditor.all.min.js') }}"></script>
<script src="{{ static('front/js/front_apost.js') }}"></script>
{% endblock %} {% block body %}
<form method="post">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">标题</span>
<input type="text" name="title" class="form-control">
</div>
</div> <div class="form-group">
<div class="input-group">
<span class="input-group-addon">版块</span>
<select name="board_id" class="form-control">
{% for board in boards %}
<option value="{{ board.id }}">{{ board.name }}</option> {% endfor %} </select>
</div>
</div> <div class="form-group">
<script id="ueditor" type="text/plain" style="height:500px;"></script>
</div> <div class="form-group">
<button class="btn btn-danger" id="submit-btn">发布帖子</button>
</div> </form> {% endblock %}
(6)front/js/apost.js
$(function () {
var ue=UE.getEditor('ueditor',{'serverUrl':'/ueditor/upload/'});
});
- 25.1.发布帖子后台逻辑完成
- 25.2.发布帖子界面布局完成
25-----BBS论坛的更多相关文章
- Python之路,Day17 - 分分钟做个BBS论坛
Python之路,Day17 - 分分钟做个BBS论坛 本节内容: 项目:开发一个简单的BBS论坛 需求: 整体参考"抽屉新热榜" + "虎嗅网" 实现不同 ...
- Python之路【第十八篇】Django小项目简单BBS论坛部分内容知识点
开发一个简单的BBS论坛 项目需求: 整体参考“抽屉新热榜” + “虎嗅网” 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 允许登录用户发贴.评论.点赞 允许上传文件 帖子可被 ...
- python 学习笔记二十 django项目bbs论坛
项目:开发一个简单的BBS论坛 需求: 整体参考“抽屉新热榜” + “虎嗅网” 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 允许登录用户发贴.评论.点赞 允许上传文件 帖子可 ...
- python第一百三十天 ---简单的BBS论坛
简单的BBS论坛 实现功能 git仓库地址:https://github.com/uge3/BBS 1.整体参考“抽屉新热榜” + “博客园” 2.实现不同论坛版块 3.帖子列表展示 4.个人博客主页 ...
- Django小项目简单BBS论坛
开发一个简单的BBS论坛 项目需求: 1 整体参考"抽屉新热榜" + "虎嗅网" 2 实现不同论坛版块 3 帖子列表展示 4 帖子评论数.点赞数展示 5 在线用 ...
- Python开发一个简单的BBS论坛
项目:开发一个简单的BBS论坛 需求: 整体参考“抽屉新热榜” + “虎嗅网” 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 允许登录用户发贴.评论.点赞 允许上传文件 帖子可 ...
- bbs论坛浏览器兼容性问题
一直都是在chrome上进行调试,今天终于把bbs论坛这个项目搭建完了,进入IE.Firefox看了看 吓哭了!!! 火狐 Edge chrome 特别是加了<!DOCTYPE html> ...
- 开源BBS论坛软件推荐
七款开源BBS论坛软件推荐(1) 本文介绍了七个开源的BBS论坛软件(在英文界一般叫做Forum).可能国内的朋友们比较熟悉Discuz!和PHPwind,但其实我们的选择还是很多的,而且下面介绍的这 ...
- LNMP环境搭建BBS论坛及伪静态
我们在mysql备份 LNMP环境中的数据库迁移为独立的服务器的基础上搭建BBS论坛: [root@bqh-117 ~]# mysql -uroot -p123456 Welcome to the ...
- Django项目 BBS论坛
BBS论坛 一.项目表分析 二.自定义form组件 三.注册功能 四.BBS论坛 登录功能
随机推荐
- php学习笔记-return语句
一个函数中可以有return语句,也可以没有.什么时候需要呢?就是当你想接收函数的执行结果的时候,你需要一个return 语句. 函数执行完return语句之后,return语句后面的代码是永远不会得 ...
- 两个进程之间的通讯——pipe 管道
在实际工作中,已经编辑好了NIPT_analysis的软件,该软件一般的输入文件是sam文件,但是为了集成进入测序仪器,需要直接从比对软件的标准输出中读取sam文件,省去了比对软件和NIPT_anal ...
- Luogu 3479 [POI2009]GAS-Fire Extinguishers
补上了这一道原题,感觉弱化版的要简单好多. 神贪心: 我们设$cov_{x, i}$表示在$x$的子树中与$x$距离为$i$的还没有被覆盖到的结点个数,设$rem_{x, i}$表示在$x$的子树中与 ...
- git clone Timed out 解决
因为不可抗拒的原因,在乌鲁木齐从 github 上面克隆项目时,会超时克隆不了. 使用 https 方式报错: $ git clone https://github.com/xxx.git Cloni ...
- 数据结构_just_sort
问题描述 给定两个序列 a b,序列 a 原先是一个单调递增的正数序列,但是由于某些原因,使得序列乱序了,并且一些数丢失了(用 0 表示).经过数据恢复后,找到了正数序列 b ,且序列 a 中 0 的 ...
- 'module' object has no attribute 'contrib'
Problem solved, turns i had 2 tensorflow versions installed: When launching $python , it used 0.6 ve ...
- WebGoat系列实验Denial of Service & Insecure Communication
WebGoat系列实验Denial of Service & Insecure Communication ZipBomb 服务器仅接收ZIP文件,将上传的文件解压,进行操作之后删除.已知服务 ...
- 《网络攻防》 第十二周作业 SQL注入
SQL注入实践 1.打开seed虚拟机,使用命令sudo service apache2 start启动apache,发现一条提示,意思就是不能可靠地确定域名,如图 即使右下角标着OK,但我还是不放心 ...
- WSMBT Modbus & WSMBS Modbus 控件及注册机
先上注册机 点击下载 How to add the WSMBT control to the toolbox: On the Tools menu, click Choose Toolbox Item ...
- SQL XML示例
declare @xmlDoc xml,@id varchar(50); set @xmlDoc='<DocObjContent> <NewCtrl Id="0001&qu ...