趁着周末,搞了一个在线的markdown编辑工具基于Editor.mdPythonFlaskFlask_SQLAlchemysm.ms
Posted @魏大大(⑉°з°)-♡
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了趁着周末,搞了一个在线的markdown编辑工具基于Editor.mdPythonFlaskFlask_SQLAlchemysm.ms相关的知识,希望对你有一定的参考价值。
在线markdown平台搭建
文章目录
前言
所谓天下代码一大抄,抄来抄去有提高,用来描述编程再合适不过了,今天我也抄了一波。我通过开源+借鉴的方式,自己搞了一个在线的markdown
编辑器,没错这篇文章就是在上面写的。
测试链接:Markdown-online
密码:996996, 帐号:666@666.com
代码很脆弱,跪求大佬不要瞎搞
话不多说,先上图,下面就是我抄的成果:
目的
我之前一直都是使用vscode
敲各种代码的,我非常喜欢这个工具,主要是颜值把住了我,其次通过插件可以支持非常多的语言,通用性非常高,上一个被我这么宠幸的IDE还是eclipse
。
我写文章使用的是markdown
,之前也用过富文本编辑器,相比于markdown
,富文本编辑器更多样,这是优势也是劣势。主要的缺点是写出来的文章比较花哨(对我来说,有很多读者都喜欢这种),而且非常容易造成自己写的文章格式风格不统一。
我一直用vscode
编写markdown
,Markdown All in One
这个插件非常的神器,基本上能用到的功能都有涉及。
问题在于代码的同步,最初都是用Gitee
,因为GitHub
老是打不开。我这人有一个毛病,不喜欢同步代码,这就导致家里和公司的代码出现了不匹配,很烦。
当然,代码同步只是一个方面,最主要的是,如果在公司打开一个黑乎乎的vscode
很引人注意(我的岗位不需要敲代码),这就有了划水的嫌疑。
另外呢,我买的还有两台服务器,域名也收藏了好多,正好用上。其实用vscode
连接远端服务器也蛮好的,但是问题还是在工位上打开vscode
不合适~~
(把vscode
改成light
主题??哈哈)
话说我还买了好几个中文域名,太费钱了
需求
为了解决我遇到的困扰,我收集了一下我的主要矛盾:
- 代码自动同步;
- 界面简洁低调;
- 良好的markdown编辑体验
我目前了解到的、喜欢的开源在线编辑工具主要有两个:
Editor.md
是一个网页版的markdown
编辑器,界面风格非常简洁,Demo
也非常丰富,也是本文的选择。遗憾的是代码库停止更新了。
CKEditor
是一个富文本编辑器,就能力上来说,更强,但是是一个富文本编辑器,虽然支持markdown
,对我来说有那么一奈奈的功能过剩。
这两款编辑工具都非常优秀,我非常喜欢,只恨自己不是开发者~~
设计
原计划只做一个页面,其他功能以弹窗的方式实现,但是Editor
和bootstrap
等前端框架有冲突,自己前端水平有限,做不出好看的界面,就能简则简。
前端页面设计
页面包括三个:
- 登录/注册页,登录注册二合一;
- 文章列表页,展示编辑过的文章;
- 编辑页面,使用
Editor.md
实现;
后端框架选择
所谓,人生苦短,我用Python
,顺理成章的就选择了Flask
作为后端框架。
Flask框架
简单介绍一下Flask
,Python
服务器开发的流行框架,非常的轻量,同时插件很丰富,文档也齐全,有兴趣的童鞋可以访问官网,或则访问我之前写的文章《我用Python写网站》,文章写的比较粗,但是基本的注意事项都提到了。
数据库选择
sqlite
是常用的单机数据库解决方案,完全能够满足我当前的需求,就不折腾mysql
了。也非常推荐简单玩玩的童鞋使用,MySQL
如果不是老鸟,太难了~💔
我之前的文章使用的是MySQL
,详细介绍了如何连接数据库,使用起来都差不多。
连接数据库的工具是flask-sqlalchemy
,SQLAlchemy
是一个ORM
(Object Relational Mapper
)框架,简单来讲,就是可以在不写sql
的情况下完成各种数据库操作。
图床sm.ms
因为贫穷,只能使用免费的图床平台,这里我用的是sm.ms
。
市面上有很多图床可以选择,一般都有免费空间赠送,sm.ms
有5GB
的免费空间,支持API
上传,不过访问速度一般,可能因为我是白嫖的。
关键是不需要注册就能使用,直接上传图片就可以获得链接。
实现
下面是抄袭教程:
数据库设计
数据库使用flask-sqlalchemy
连接,详细操作在《我用Python写网站》中都有讲解。
下面的代码涉及了flask-sqlalchemy
的使用方法、flask-cli
命令行的使用。
可以简单的使用flask db-init
、flask db-rebuild
等命令操作数据库。
话不多说,上代码:
# db.py
from email.policy import default
from flask_sqlalchemy import SQLAlchemy
import sqlite3
import click
from flask.cli import with_appcontext
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
db = SQLAlchemy()
def addUser(u):
if isinstance(u, User):
db.session.add(u)
db.session.commit()
def updatePost(p):
if isinstance(p, Post):
db.session.add(p)
db.session.commit()
def init_app(app):
db.init_app(app)
app.cli.add_command(init_db_command)
app.cli.add_command(reb_db_command)
app.cli.add_command(del_db_command)
def init_data():
admin = User(username='admin', password='996996', email='666@163.com')
db.session.add(admin)
db.session.flush()
db.session.commit()
post = Post(title='第一篇文章', html='# 第一篇文章', markdown='# 第一篇文章')
post.author_id = admin.id
db.session.add(post)
db.session.commit()
anonym = User(username='anonym', password='996996', email='666@666.com')
db.session.add(anonym)
db.session.commit()
def init_db():
db.create_all()
init_data()
def del_db():
db.drop_all()
@click.command('db-rebuild')
@with_appcontext
def reb_db_command():
del_db()
init_db()
click.echo('Rebuild the database.')
@click.command('db-clean')
@with_appcontext
def del_db_command():
del_db()
click.echo('Cleared the database.')
@click.command('db-init')
@with_appcontext
def init_db_command():
init_db()
click.echo('Initialized the database.')
class ShareField(object):
created = db.Column(
db.DateTime, nullable=False, default=datetime.utcnow)
updated = db.Column(db.DateTime, onupdate=datetime.utcnow)
status = db.Column(db.Integer, default=0)
class User(db.Model, ShareField, UserMixin):
__tablename__ = 't_users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), nullable=False)
_password = db.Column(db.String(128), nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
posts = db.relationship('Post', backref='author', lazy=True)
def __init__(self, username, password, email):
self.username = username
self.password = password
self.email = email
# getter
@property
def password(self):
return self._password
# setter
@password.setter
def password(self, raw_password):
self._password = generate_password_hash(raw_password) # 加密
# check
def check_password(self, raw_password):
result = check_password_hash(self.password, raw_password)
return result
class Post(db.Model, ShareField):
__tablename__ = 't_posts'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(64), nullable=False, default='')
html = db.Column(db.String(30000), nullable=False, default='')
markdown = db.Column(db.String(30000), nullable=False, default='')
author_id = db.Column(db.Integer, db.ForeignKey(
't_users.id'), nullable=False)
登录注册
首先,去csdn
上搜个登录注册页面源代码!
我选择的是《好看实用的HTML登录界面》
稍微改改里面的form
代码,以下仅供参考:
<div class="container__form container--signup">
<form action="url_for('auth.register')" method="post" class="form" id="form1">
<h2 class="form__title">Sign Up</h2>
<input type="text" name="username" placeholder="UserName" class="input" />
<input type="email" name="email" placeholder="Email" class="input" />
<input type="password" name="password" placeholder="Password" class="input" />
<input type="submit" class="btn" value="Sign Up"></input>
</form>
</div>
<!-- Sign In -->
<div class="container__form container--signin">
<form action="url_for('auth.login')" method="post" class="form" id="form2">
<h2 class="form__title">Sign In</h2>
<input type="email" name="email" placeholder="Email" class="input" />
<input type="password" name="password" placeholder="Password" class="input" />
<a href="#" class="link">Forgot your password?</a>
<input type="submit" class="btn" value="Sign In"></input>
</form>
</div>
后端使用flask-login
插件完成登录,如果不会用这个插件的,可以访问我之前的文章《我用Python写网站》。
@bp.route('/register', methods=['POST', 'GET'])
def register():
if request.method == 'POST':
email = request.form.get('email', '')
username = request.form.get('username', '')
password = request.form.get('password', '')
if email == '' or username == '' or password == '':
flash('注册信息不完整')
return 'msg': '注册信息不完整', 201
user = User.query.filter_by(email=email).first()
if user:
flash('邮箱已注册')
return 'msg': '邮箱已注册', 201
user = User(email=email,username=username,password=password)
addUser(user) #插入数据库
return redirect(url_for('auth.login'))
return render_template('sigh.html')
@bp.route('/login', methods=['POST', 'GET'])
def login():
if request.method == 'POST':
email = request.form.get('email', '')
password = request.form.get('password', '')
print(email, password)
if email == '' or password == '':
flash('登录信息不完整')
return 'msg': '登录信息不完整', 201
user = User.query.filter_by(email=email).first()
if not user:
flash('用户不存在')
return 'msg': '用户不存在', 404
if not user.check_password(password):
flash('密码错误')
return 'msg': '密码错误', 201
login_user(user)
return redirect(url_for('post.all'))
return render_template('sign.html')
以上代码写的非常粗糙,基本上没有异常的处理,而且登录失败没有页面跳转😫,可以稍微改下。
文章编辑
主要是Editor.md
的引入,同样的,《我用Python写网站》里面也都有,我这里直接上代码:
index.html
% extends 'base.html' %
% block style %
super()
<link rel="stylesheet" href=" url_for('static',filename='css/editormd.css')" />
% endblock %
% block content %
<div class="main_content">
<div class="center_content">
<div class="btn-group">
<button id="show-btn">Show editor</button>
<button id="hide-btn">Hide editor</button>
<button id="get-md-btn">Get Markdown</button>
<button id="get-html-btn">Get HTML</button>
<button id="show-toolbar-btn">Show toolbar</button>
<button id="close-toolbar-btn">Hide toolbar</button>
% if current_user.is_authenticated %
<a class="link-btn" href="url_for('auth.logout')">Quit</a>
<a class="link-btn" href="url_for('post.all')">Post List</a>
% else %
<a class="link-btn" href="url_for('auth.register')">Sign Up</a>
<a class="link-btn" href="url_for('auth.login')">Sign In</a>
%endif%
</div>
<input id="title" name="title" type="text" value="target.title" style="width: 100%;" placeholder="请输入文章标题">
</div>
<div id="test-editormd">
<textarea style好用的在线Markdown编辑器