一、安装markdown插件
pip install django-mdeditor
pip install markdown
二、自定义modle和form
models.py
from django.db import models
from mdeditor.fields import MDTextField
class Markdown(models.Model):
title = models.CharField(max_length=50)
markdown_text = MDTextField()
html_text = models.TextField()
datetime = models.DateTimeField()
form.py
from django import forms
from mdeditor.fields import MDTextFormField
class MarkdownForm(forms.Form):
title = forms.CharField(max_length=50)
markdown_text = MDTextFormField(label="", widget=forms.TextInput(attrs={'class': 'form-control'}),
max_length=65535)
编写视图
views.py
from django.shortcuts import render, redirect, reverse
from django.views import View
from .forms import MarkdownForm
from .models import Markdown
import markdown
class NewTask(View):
def get(self, request):
form = MarkdownForm()
context = {'form': form}
return render(request, 'task/new_task.html', context=context)
def post(self, request):
markdown_text = request.POST['markdown_text']
html_text = markdown.markdown(markdown_text)
new_markdown = Markdown()
new_markdown.markdown_text = markdown_text
# html_text 指的是 markdown_text 渲染出来的 HTML 代码
# 渲染了这一次,以后都不用渲染了
new_markdown.html_text = html_text
new_markdown.save()
return redirect(reverse('task:task'))
配置路由
在项目的urls.py文件中添加
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('task/', include('Ebbinghaus.task.urls', namespace='task')),
path(r'mdeditor/', include('mdeditor.urls')),
]
在App的urls.py中添加
from django.urls import path
from Ebbinghaus.task import views
app_name = 'task'
urlpatterns = [
path('newtask', views.NewTask.as_view(), name='newtask'),
]
五、添加模板
html文件
{% extends 'base/base.html' %}
{% block content %}
<form class="layui-form" method="post" action="{% url 'task:newtask' %}">
<div class="layui-form-item">
<label class="layui-form-label">标题</label>
<div class="layui-input-block">
<input type="text" name="title" required lay-verify="required" placeholder="请输入标题"
autocomplete="off" class="layui-input">
</div>
</div>
{% csrf_token %}
{# 添加markdown所需的js和css文件#}
{{ form.media }}
{# 添加markdown编辑框 #}
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="submitMarkdown">立即提交</button>
</div>
</div>
</form>
{% endblock %}
六、添加media配置
添加media用于存储图片。
在settings.py文件添加
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
在项目urls.py中添加
if settings.DEBUG: # 如果正在调试模式下的话
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
七、效果展示
八、解决BUG
上传图片,链接无法回填
在上传图片过程中,出现图片能保持到后端,但是前端界面的图片链接无法回填,在使用浏览器调试的console页面中有如下的提示信息:Refused to display ‘页面url’ in a frame because it set ‘X-Frame-Options’ to ‘deny’.
那么就知道是是X-Frame-Options设置出了问题。
有关X-Frame-Options
1、什么是X-Frame-Options
X-Frame-Options HTTP 响应头是用来给浏览器指示允许一个页面可否在
2、X-Frame-Options选项
X-Frame-Options 有三个值:
DENY :表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许
SAMEORIGIN :表示该页面可以在相同域名页面的 frame 中展示
ALLOW-FROM uri :表示该页面可以在指定来源的 frame 中展示
换一句话说,如果设置为 DENY,不光在别人的网站 frame 嵌入时会无法加载,在同域名页面中同样会无法加载。
另一方面,如果设置为 SAMEORIGIN,那么页面就可以在同域名页面的 frame 中嵌套。
Django有关配置
1、Django默认的配置
首先,Django起禁止X-Frame-Options,使用默认设置了相关的配置。
在项目的setting.py页面中能够找到如下的设置:
MIDDLEWARE = [
...
'django.middleware.clickjacking.XFrameOptionsMiddleware',
...
]
上面的内容显示,Django的项目中默认设置了XFrameOptionsMiddleware的中间件,这个设置将对于X-Frame-Options的配置设置成了DENY。
在Django 3.0中,X_FRAME_OPTIONS的默认设置从SAMEORIGIN 变成了DENY。
2、Django总体配置
想要总体设置项目的X-Frame-Options可以在settings.py中添加如下的代码:
X_FRAME_OPTIONS = 'SAMEORIGIN'
可以看出上面的是将X_FRAME_OPTIONS设置成SAMEORIGIN,但是这个改变了整个项目的设置,往往只有某些页面才需要这样的设置,因此下面介绍在单独的页面上设置这些内容。
3、指定的网页配置
直接看代码:
from django.http import HttpResponse
from django.views.decorators.clickjacking import xframe_options_exempt
from django.views.decorators.clickjacking import xframe_options_deny
from django.views.decorators.clickjacking import xframe_options_sameorigin
@xframe_options_exempt
def view_one(request):
return HttpResponse("This page is safe to load in a frame on any site.")
@xframe_options_deny
def view_two(request):
return HttpResponse("I won't display in any frame!")
@xframe_options_sameorigin
def view_three(request):
return HttpResponse("Display in a frame if it's from the same origin as me.")
使用markdown解析md语法为html问题
markdown语法中的换行符会被markdown库解析成\n,解析后的HTML格式中含有\n符,但是\n符在HTML页面不生效,如果全部使用white-space: pre-line;,像h等标签会自动换行,也就会换两次行,我发现,我们希望他换行的地方,基本都在p标签中,我们只要让p标签中的换行符生效就行。解决方法:
<style>
p {
{#让p标签中的\n符生效#}
white-space: pre-line;
}
</style>