文末附源码
之前写的《在线Markdown编辑系统》本来只是自己瞎搞的,没想到用起来真香~~
而且,还有很多童鞋对之前的叙利亚战损版系统非常感兴趣,正好趁着五一放假,我花了两天时间重构了之前的系统,引入了前端框架,使界面看起啦更统一,同时也增加了一些其他的功能。
不过,关于Flask
搭建的文章,我写太多了,感觉有点皮了,本文就不再做过多解读,有兴趣的可以看我之前的文章《我用Python写网站》,有点粗糙,还能看吧。
如果,有人想了解更多可留言催更,最近在研究JS
,精力分散了。
下面是截图加简介时间:
预览地址:Markdown-Online
有兴趣的同学可以访问以上链接,注册个账号瞅一瞅,不要用手机打开,没有针对移动端做设计~~
以下是系统的主页,啥也没有~~
登录界面
Flask
开发的标准步骤:wtf
表单创建、html
代码编写,最后是视图函数,当然不同的人顺序可能稍有区别.
使用Flask-wtf
的最大好处就是表单的验证,其次就是配合Bootstrap
能够快速生成的简单的界面。
首先是LoginForm
的代码:
# forms.py
class LoginForm(FlaskForm):
email = EmailField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
submit = SubmitField('Sign In')
然后是对应的html
<!-- login.html -->
{% extends 'base.html' %}
{% from 'bootstrap5/form.html' import render_field %}
{% block content %}
<div style="height: 600px; padding-top: 100px;">
<div style="width: 36rem;" class="mx-auto shadow-sm px-3 py-5 bg-body rounded">
<h2>Sign In</h2>
<hr>
{% for msg in get_flashed_messages() %}
<p class="text-sm-start text-warning">{
{msg}}</p>
{% endfor %}
<form method="post">
{
{ form.csrf_token() }}
{
{ render_field(form.email,placeholder='Your email')}}
{
{render_field(form.password,placeholder='Your password')}}
{
{render_field(form.submit)}}
<a class="btn btn-light" href="{
{url_for('auth.register')}}"> Sign Up</a>
</form>
</div>
</div>
{% endblock %}
最后是对应的后端view
代码:
@bp.route('/login', methods=['POST', 'GET'])
def login():
print('auth/login')
loginForm = LoginForm()
if loginForm.validate_on_submit(): #登录
print('validated')
email = loginForm.email.data
password = loginForm.password.data
user = User.query.filter_by(email=email).first()
if not user:
flash('User does not exist')
return render_template('login.html', form=loginForm)
if user.role >= const.DB_ROLE_VISITOR:
flash('Please verify the mailbox first')
return redirect(url_for('auth.email_verify'))
if not user.check_password(password):
flash('Incorrect password')
return render_template('login.html', form=loginForm)
login_user(user)
return redirect(url_for('post.list'))
return render_template('login.html', form=loginForm)
注册界面
注册界面的代码和登录几乎没有太大的区别。
首先是注册表单:
class RegisterForm(FlaskForm):
email = EmailField('Email', validators=[DataRequired(), Email()])
username = StringField('Username', validators=[DataRequired(), Length(min=3, max=16)])
password = PasswordField('Password', validators=[DataRequired(), Length(min=6, max=12)])
submit = SubmitField('Sign Up')
然后是对应的前端代码:
<!-- register.html -->
{% extends 'base.html' %}
{% from 'bootstrap5/form.html' import render_field,render_form_row %}
{% block content %}
<div style="height: 600px; padding-top: 100px;">
<div style="width: 36rem;" class="mx-auto shadow-sm px-3 py-5 bg-body rounded">
<h2>Sign Up</h2>
<hr>
{% for msg in get_flashed_messages() %}
<p class="text-sm-start text-warning">{
{msg}}</p>
{% endfor %}
<form method="post">
{
{ form.csrf_token() }}
{
{ render_field(form.email,placeholder='Enter your email address')}}
{
{ render_field(form.username,placeholder='Make a name you like')}}
{
{render_field(form.password,placeholder='Create a strong password')}}
{
{render_field(form.submit)}}
<a class="btn btn-light" href="{
{url_for('auth.login')}}"> Sign In</a>
</form>
</div>
</div>
{% endblock %}
最后是视图代码:
@bp.route('/register', methods=['POST', 'GET'])
def register():
print('auth/register')
registerForm = RegisterForm()
if registerForm.validate_on_submit():
print('validated')
email = registerForm.email.data
username = registerForm.email.data
password = registerForm.password.data
user = User.query.filter_by(email=email).first()
if user:
flash('Mailbox registered')
return render_template('register.html', form=registerForm)
user = User(email=email, password=password, username=username)
addUser(user)
newPost(user) # 为当前用户添加一个文章
return redirect(url_for('auth.email_send', emailbox=email))
return render_template('register.html', form=registerForm)
密码修改
密码修改表单:
class RePasswardForm(FlaskForm):
password = PasswordField('Original Password', validators=[DataRequired()])
newpaswd = PasswordField('New Password', validators=[DataRequired(), Length(min=6, max=12)])
confpswd = PasswordField( 'Confirm Password', validators=[DataRequired(), Length(min=6, max=12)])
submit = SubmitField('Confirm')
密码修改界面:
{% extends 'base.html' %}
{% from 'bootstrap5/form.html' import render_field %}
{% block content %}
<div style="height: 600px; padding-top: 100px;">
<div style="width: 36rem;" class="mx-auto shadow-sm px-3 py-5 bg-body rounded">
{% for msg in get_flashed_messages() %}
<p class="text-sm-start text-warning">{
{msg}}</p>
{% endfor %}
<form method="post">
{
{ form.csrf_token() }}
{
{ render_field(form.password) }}
{
{ render_field(form.newpaswd) }}
{
{ render_field(form.confpswd) }}
{
{ render_field(form.submit) }}
<a class="btn btn-light" href="{
{url_for('auth.register')}}"> Sign Up</a>
</form>
</div>
</div>
{% endblock %}
密码修改后端代码:
@login_required
@bp.route("/resetpwd/<int:id>", methods=['GET', 'POST'])
def resetpwd(id):
print('auth/resetpwd')
resetForm = RePasswardForm()
if resetForm.validate_on_submit():
password = resetForm.password.data
newpaswd = resetForm.newpaswd.data
if not current_user.check_password(password):
flash('The original password is incorrect')
return render_template('reset_pwd.html', form=resetForm)
current_user.password = newpaswd
updateUser(current_user)
return redirect(url_for('auth.logout'))
return render_template('reset_pwd.html', form=resetForm)
邮箱验证
这也是本次更新的重点,用户在注册账号之后,系统会对注册邮箱发送一封邮件,用户在没有验证邮箱之前不能登录系统。
前后端的处理和之前一样,本次不再重复,只贴一段flask-email
的使用代码:
@bp.route('/email_send/<emailbox>')
def email_send(emailbox):
# 发送邮箱验证码
print('email_send')
user = User.query.filter_by(email=emailbox).first()
if not user:
return '404'
if user.role >= const.DB_ROLE_BAD:
flash('Sorry!')
return '404'
msg = Message('Mailbox verification - Markdown-Online',
sender=current_app.config['MAIL_USERNAME'],
recipients=[emailbox])
code = random.randint(100000, 999999)
msg.body = "Your verification code is:" + str(
code) + "\n Please keep it safe."
send_async_email(msg)
user.status = code
user.role += 1
updateUser(user)
return redirect(url_for('auth.email_verify'))
以上代码会向目标邮箱发送一封带有验证码的邮件。
使用flask-email
插件,需要配置的参数:
SECRET_KEY = b'_5#y2L"99567\n\xec]/' # Flask需要的密钥,一个复杂的字符串即可
ICP='京ICP备20210xxxxxx号' # 网站的备案号,需要备案才能获得
MAIL_SERVER = 'smtp.qq.com' # 发送邮件需要的smtp服务器,这里是qq邮箱的
MAIL_PORT = 465 # 端口,一般都是465,如果使用163邮箱,可以百度一下
MAIL_USE_SSL = True # SSL加密的传输方式
MAIL_USE_TSL = False # 传统的传输方式
MAIL_USERNAME = '[email protected]'# 这是你想用来发邮件的邮箱,可以填你自己的邮箱
MAIL_PASSWORD = 'wtvcrkyjzlagbadg' # 邮箱的授权码,但是需要去申请一个
HOST_NAME='www.weidawang.site' # 这是我的域名,写不写都行
SMMS_AUTHORIZATION='7qV3kO1Fc8U6ixxxxxx'# sm.ms图床的授权码,上文介绍了获取方式
文章列表
支持分页,删除文章,这里还有一个admin
按钮,可以跳转管理员界面。普通用户看不到这个按钮。
文章编辑
这里和之前没有什么两样。
编辑器主题
在编辑器的下面,是编辑器的主题选择,可以选择工具条、编辑区、预览区的主题风格。
尤其是编辑区,有多种可选的主题。
管理页面
这里是简单的管理页面,虽然页面看起来非常简单,但是包括了权限管理、用户删除等多种功能。
其中,管理员显示红色,并有特殊标记,用户、游客、封号都有不同的颜色和标记。
管理员可以授权普通用户成为管理员,也可以删除管理员的管理权限。
系统虽小,五脏俱全,肝了两天,好累~~
欢迎大家体验,我这里就不详细介绍了,睡了睡了
预览地址:Markdown-Online
代码下载:Markdown-Online
原文 我的创业之路——宁可啃馒头打地铺,也要当老板“宁可啃馒头打地铺,也要当老板”——题记家人的影响,让我热血沸腾 我生在一个不富裕的家庭,家里有四个小孩,大哥,我,小弟,妹妹。年纪都差别不大,之前同时读大学的时候,家里的经济压力特别大,父亲虽然愁白了头,表面 却装的若无其事;所以,老大大学时候,开始做兼职,KFC,便利店都做过店员。之后,开始在校园做生意,通过他独特的营销模...
原始的:using UnityEngine;using System.Collections;public class NGUIJoystick : MonoBehaviour{ public float radius = 2.0f; public Vector3 scale = Vector3.one; private Plane ...
分享独立开发、产品变现相关内容,每周五发布。目录1、Blocksurvey: 面向Web3实现的表单填写2、Tactiq:一个远程视频会议记录的浏览器扩展,目标收入150万美金3、NFTs...
vue结合百度地图实现热力图功能描述 结合百度地图实现热力图功能我们可在[Apache ECharts](https://echarts.apache.org/examples/zh/index.html#chart-type-heatmap)看到示例代码,实现效果大致如下。插件安装npm 安装$ npm install vue-baidu-map --savepackage.json引入"vue-baidu-map": "0.21.22"vue页面实现script代码
开发十年,就只剩下这套架构体系了!>>> ...
Webpack从入门到精通-进阶篇目录Webpack从入门到精通-进阶篇一、create-react-app react-project二、vue create vue-project三、自定义loader3.1预备知识3.2自定义babel-loader四、自定义plugin4.1 预备知识-compiler钩子4.1.2 tapable4.1.2 compiler钩子4.2 预备知识-compilation钩子4.2.1 小插曲:nodejs环境中调试4.2.2 compilation钩子4.3 自定
缘起早在2015年的时候,随着阿里云业务突飞猛进的发展,SQLServer业务也积累了大批忠实客户,其中一些体量较大的客户在类似大促的业务高峰时RDS的单机规格(规格是按照 内存CPUIOPS 一定比例分配,根据底层资源不同都会有各自上限)已经不能满足用户的业务需求,在我们看来也需要做Scale Out了,但SQLServer并没有完备的中间件产品,所以无论是逻辑Sharding还是只读分离,...
摘要:随着计算机科学水平的发展,外语教学也正经历着一场以教师为中心的教学模式向以学生为中心的模式发展。本文通过对当今计算机辅助教学地位和现状进行以及相关辅助教学理论进行分析,从而试图寻找一种计算机辅助外语教学以到达理想教学效果的可操作模式。关键词:计算机辅助教学 外语教学 效用1.计算机辅助外语教学的地位我们选择将计算机与外语教学相融合,不是因为在这个信息发达的高科技时代,缺了多媒体,英语教学就不...
一、时间类/** * 时间日期格式化工具类 */public class DateTimeUtil { /** * 日期格式:yyyy-MM-dd HH:mm:ss **/ public static final String DF_YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; /** ...
Python Lambda的使用一、Lambda的直观含义上面是Python里面Lambdas文档的截图,划个重点,就是简洁的匿名函数原先的函数如下:def <lambda>(arguments): return expression通过Lambda表达式,可以简化成如下形式:"lambda" [parameter_list]: expression二、直接定义Lambda单个参数的情况f = lambda x: -xprint(f(2))print(f(-3)
前言: 今天给同学讲一下布局和MVC封装的过度 那么就建一个九宫格的项目给同学们瞅瞅!那么废话不多说,上代码! //// ZZViewController.h// 九宫格多种实现//// Created by 周昭 on 16/10/20.// Copyright 2016年 HT_Technology. All rights reserved.//...
set val(simDur) 85.0;#simulation durationset val(basename) multi-hop;#basename for this project or scenarioset val(statIntvl) 0.1 ;#statistics collection intervalset val(statStart) 0.5 ;...