IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Django markdown 使用(admin后台md编辑器,前端显示,前端md编辑器) -> 正文阅读

[Python知识库]Django markdown 使用(admin后台md编辑器,前端显示,前端md编辑器)

前言

吐槽一波,网上的教程都是小可爱。都他喵的是抄的,关键是还抄不好,害的我踩了不少坑。而且现在关于这方面从我目前查的资料来看都不全面,基本上都只是在后端使用markdown编辑器然后在前端显示,但是开玩笑,后端用只能做个个人博客网站用,那玩意django自带一个要你写有毒啊?而且所谓的教程连个案例都没有,还得我自己去找找,去看看官方文档什么的。然后就是那个django网上大部分的教程用的插件是django-mdeditor,但是这玩意其实只是用于后端页面的markdown编辑器显示的。如果要玩前端的编辑器我们应该玩的是editor.md这一个开源的适用于前端的markdown编辑器,那个插件也是基于这个来玩的。这里的话做个全面一点的总结,没办法鄙人要搞个技术交流博客社区,不得不用这个,如果用富文本编辑器的话,虽然很成熟,但是用起来和shit一样。
最后本文是本博主踩坑制作,也是white Hole的开发历程之一 White Hole 详情
一定要仔细看此博文,被坑了不要怪我没提醒

准备环境

想要用那必然是要安装相应的环境。那么这里准备安装四个玩意

1.pip install django-mdeditor  # 用于后台编辑
2.pip install markdown # 用于前端显示
3.pip install Pygments # 用于前端显示markdown里面写的代码的高亮
4.editor.md 开源的前端的编辑器的源码,这个在GitHub上,下载解压(好像也有官网)

首先前面那三个玩意,直接下载就好了,怎么配置待会说。

后面那个请移步官网下载,解压,然后放到你django项目的static文件下面。例如:
请添加图片描述
这个是editor.md的源码

在后端页面编辑

这个是真的简单,主要使用的就是django-mdeditor这个插件,接下来分几个小步。

注册插件

首先找到settings然后注册。
请添加图片描述
这个是那个django-mdeditor插件的app

然后再加入下面几个配置

MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')  #新建一个uploads文件夹,且在项目目录下
MEDIA_URL = '/media/'   #你上传的文件和图片会默认存在/uploads/editor下 这一步不用创建任何文件夹,这个是那个插件帮我们做好了,做好了一个图片上传,后面我们自己在前端做编辑器的话我么还要自己再实现一个。

路由注册

接下来注册一个路由就好了。找到你的路由文件,写入如下代码。

urlpatterns = [
    path('admin/',admin.site.urls),
    url(r'mdeditor/', include('mdeditor.urls')),
]

if settings.DEBUG:
    # static files (images, css, javascript, etc.)主要是让页面显示正常
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

模型建立并在admin注册

首先创建一个app或者在你的app里面的modules里面创建模型。

class ExampleModel(models.Model):
    name = models.CharField(max_length=10)
    content = MDTextField()

这个是官方文档里面的一个示例。

请添加图片描述

之后迁移注册在admin里面(在你APP的admin.py里面)请添加图片描述

from django.contrib import admin
from . import models

admin.site.register(models.ExampleModel)

请添加图片描述

检验

接下来就是那个验证了,进入后台。

请添加图片描述

进入后台编辑

请添加图片描述

前端显示

注册一个路由,然后编写view就不要复述了吧。

现在数据库已经把博客写进去了。

Pygments生成样式

先激活一下Pygments,生成这个css渲染文件

进入你想要放css文件的地方在终端执行:

pygmentize -S default -f html -a .codehilite > code.css

那个default只是一个样式

此外支持的样式还有

default
emacs
friendly
colorful
autumn
murphy
manni
monokai
perldoc
pastie
borland
trac
native
fruity
bw
vim
vs
tango
rrt
xcode
igor
paraiso-light
paraiso-dark
lovelace
algol
algol_nu
arduino
rainbow_dash
abap

我这里用的是monokai

pygmentize -S monokai -f html -a .codehilite > monokai.css

模板于views的编写

到这里就可以编写模板了

<!DOCTYPE html>
<html lang="en">
{% load static %}
<head>
    <meta charset="UTF-8">
    <title>Show</title>

    <link rel="stylesheet" type="text/css" href="{% static 'md_css/monokai.css' %}">
</head>
<body>

<div>
    {{ article.content|safe }}
</div>

</body>
</html>

然后编写我们的view

def show(request):
    article = ExampleModel.objects.get(id=2)#我这里这是做个显示写死了
    # 将markdown语法渲染成html样式
    article.content = markdown.markdown(article.content,
                                     extensions=[
                                         'markdown.extensions.extra',
                                         'markdown.extensions.codehilite',
                                         'markdown.extensions.toc',
                                     ])
    context = {'article': article}
    return render(request, 'blogedit.html', context)

markdown.extensions.extra:用于标题、表格、引用这些基本转换

markdown.extensions.codehilite:用于语法高亮

markdown.extensions.toc:用于生成目录

效果如下:

请添加图片描述

全屏可能不好看那就改改div布局。

前端markdown编辑器

重点来了。

这个我是直接用editor.md做的,其实这些插件都是基于这个来做的,毕竟开源的东西嘛。

前端模板编写

我这里的话直接把我正在做的博客编辑页面的代码拿过来,反正那个做好了也是开源的。

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Markdown Editor</title>
    <link rel="stylesheet" href="{% static 'mdeditor/css/editormd.css' %}"/>
</head>
<style>
    #center {
        margin-top: 5%;
        width: 96%;
        height: 96%;
        border: 1px;
    }

    img {
        margin: auto;
        margin-left: 30%;
        height: 40%;
        width: 40%;
        position: relative;
        top: 10%;
    }

    input {

        width: 85%;
        height: 30px;
        border-width: 2px;
        border-radius: 5px;
        border-color: #00c4ff;
        border-bottom-color: #2C7EEA;
        color: #586e75;
        font-size: 15px;

    }

    button {
        width: 10%;
        height: 35px;
        border-width: 0px;
        margin-left: 3%;
        border-radius: 10px;
        background: #1E90FF;
        cursor: pointer;
        outline: none;
        font-family: Microsoft YaHei;
        color: white;
        font-size: 17px;
    }
        button:hover {
        background-color: #1E90FF;
        box-shadow: 0 4px 0 powderblue;
    }
</style>
<body>
{% csrf_token %}
<form method="post" action="{% url "save" %}" enctype="multipart/form-data">
    <div class="form-group">
        <div>
            <input type="text" name="blogname" placeholder="请输入文章标题" required>
            <button type="submit" id="submit">发布文章</button>
        </div>
        <br>
        <div id="editormd">
            {% csrf_token %}
            <textarea style="display:none;" name="blogbody" id="blogeditor"></textarea>
        </div>
    </div>

</form>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="{% static 'mdeditor/editormd.min.js' %}"></script>
<script type="text/javascript">
    $(function () {
        var editor = editormd("editormd", {
            width  : "100%",
            height : "800",
            path   : "{% static 'mdeditor/lib/' %}",
            placeholder: "请开始你的书写之旅",
            //增加图片上传配置
            imageUpload    : true,
            imageFormats   : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
            imageUploadURL : "/upload/",//图片上传的地址(在你的项目里面的路由)
            required:true,
            saveHTMLToTextarea : true,
            taskList: true,
            tocm: true,      
            tex: true,                   // 开启科学公式TeX语言支持,默认关闭
            flowChart: true,             // 开启流程图支持,默认关闭
            sequenceDiagram: true,       // 开启时序/序列图支持,默认关闭,

        });

    });
    var blogeditor = document.getElementById("blogeditor");
    blogeditor.required = true;
    var button = document.getElementById("submit");
    button.addEventListener("click",()=>{
        if(blogeditor.value==''){
            alert("博客内容不能为空");
        }
    });
</script>
</body>
</html>

这个你们自己看着改。

请添加图片描述

图片上传

这个也是比较重要的功能

这里我加入一个上传本地图片的功能。

这里再明确一下我们使用的是editor.md这个开源的玩意,所以我们的图片上传功能也要基于这个。

那么首先做一个图片上传功能其实很简单,按照我前面给的前端模板就可以看到我已经开启了,现在前端模板不用管,把视线

移步到后端即可。

首先找到项目的static文件,里面创建一个文件夹用来保存你的图片。

请添加图片描述

views 逻辑编写

由于前端已经搞好了,那么我们后端要做的就只有一个保存图片,然后告诉前端,地址在哪。

首先来看看我们应该注意的参数

我们保存图片后需要返回一个json数据

{
    success : 0 | 1,           // 0 表示上传失败,1 表示上传成功
    message : "提示的信息,上传成功或上传失败及错误信息等。",
    url     : "图片地址"        // 上传成功时才返回
}


Django跨站注意点

现在我们是上传文件一个是POST跨站Django需要验证,还有一个是文件上传也要验证,由于不方便直接在前端加入crsf_token。所以我在后端加入,此外文件的也是。

from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.clickjacking import xframe_options_sameorigin
import os
import time
import uuid

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

@csrf_exempt
@xframe_options_sameorigin
def upload(request):
    if request.method == "POST":
        obj = request.FILES.get('editormd-image-file')

        file_name = time.strftime('%Y%m%d%H%M%S') + str(uuid.uuid1().hex) + '.' + obj.name.split('.')[-1]  # 图片文件名
        data_path = time.strftime('%Y%m')
        print(data_path)
        dir_path = os.path.join(BASE_DIR, 'static', 'upload', data_path)  # 保存的文件目录
        if not os.path.exists(dir_path):
            os.makedirs(dir_path)
        img_path = os.path.join(dir_path, file_name)  # 存储的完整图片路径(绝对路径)
        f = open(img_path, 'wb')
        for chunk in obj.chunks():
            f.write(chunk)
        f.close()
        data = {"success": 1, "message": "上传成功", "url": '/static/upload/' +data_path+'/'+file_name}
        return JsonResponse(data)

    else:
        return JsonResponse({"success": 0, "message": "上传失败"})

此外关于文件上传的话还有一个解决办法,直接在设置里面设置允许,但是那个是全局的。你只需要在项目的settings加入

X_FRAME_OPTIONS = 'SAMEORIGIN'

之后就是这个文件上传的话,本来是打算用django自带的解决方案的,但是这里要返回保存地址,所以就没有办法直接用了。因为要保证文件名不重复只能这样搞个随机文件名,此外在Linux系统里面一个文件夹只能放6700多张图片

验证效果

请添加图片描述

总结

这个其实还是很简单的,但是让我很难受的是网上的一堆垃圾教程,啥也说不明白,到处都是坑,根本跑不了,很多东西都是我直接在浏览器debug出来的,就问你恶不恶心。那么之后就是建表,弄模型就好了,至于显示都是一样的。对了忘了说了,那就是在admin的那个编辑器里面想要使用上传图片也要设置一下django的允许上传,能不能指定admin那我也不清楚,不过你可以直接在settings里面去设置那个上传验证的,不过那是全局的。如果你知道记得踹我!累了不想搞了。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-10-03 17:02:17  更:2021-10-03 17:03:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 17:36:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码