ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

博客项目——〇六 添加新文章——富文本编辑器、beautifulsoup的使用

2022-01-09 02:33:14  阅读:278  来源: 互联网

标签:文本编辑 request beautifulsoup 博客 BeautifulSoup content soup 上传


我们前面在试各种功能的时候都是在admin下把数据硬插在table里,但是这明显不符合我们的日常使用环境,博客里最常用的就是添加新的文章了,所以这里我们就看一看文章的添加是怎么实现的。

富文本编辑器

 看一看博客园在添加文章的页面,新的文章是怎么添加进去的呢?

 

 这个图片里的文本编辑器就是一个富文本编辑器(富文本编辑器,Rich Text Editor, 简称 RTE, 是一种可内嵌于浏览器,所见即所得的文本编辑器。)因为我们在编辑文本的时候包含了各种各样的样式,其实真实情况下我们是写了一个html的代码,这个代码点击上面的图标是可以显示出来的,只不过富文本编辑器是一种所见即所得的效果,更利于我们的编辑。但是最终生成的还是一堆html类型的字符串。

kindeditor

在新文章的页面中我们就使用了KindEditor这个富文本编辑器,点击官网查看,下载以后放在static文件夹中,就可以直接调用了,在HTML页面中就是定义一个textarea的标签,然后导入Kindeditor,把他绑定给这个textarea

<textarea id="editor_id" name="content" style="width:700px;height:300px;">
&lt;strong&gt;HTML内容&lt;/strong&gt;
</textarea>

<script charset="utf-8" src="/editor/kindeditor.js"></script>
<script charset="utf-8" src="/editor/lang/zh-CN.js"></script>
<script>
        KindEditor.ready(function(K) {
                window.editor = K.create('#editor_id');
        });
</script>

至于create函数中还可以添加好多参数,可以直接在官网上查到。

官网上的文档说的很清楚,如何在页面中加载KindEditor,这里就不说了。但是下面的一个用法是要着重讲一下的:图片的上传。

KindEditor中上传图片

 默认的KindEditor是有两个图片上传的按钮的,但是上传以后是没有任何行为的(我们也没有告诉他上传到服务器的哪里?怎么上传)!所以我么就要给K.create()中添加下面几个参数

<script>
    KindEditor.ready(function(K){
        window.editor = K.create('#editor_id',{
            uploadJson:'/upload/',
    })
</script>

就是指定了上传图片时候对应的url请求。然后上传一下会发现有下面的错误

 

 

 很明显,发生了跨站请求错误,所以要添加csrf参数,这个参数的添加在一个新的配置参数中

1 uploadJson:'/upload/',
2 extraFileUploadParams:{
3     csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val()
4 },
5 filePostName:"upload_img"   //指定上传文件的key

但是一定要记得在前面加上{%csrf_token%}才行啊,要不是jQuery取不到这个csrf的值。

最后一行的filePostName的作用我们下面马上会说明。

既然上传图片是用到一个url,所以我们要在路由总设置好这个url和它对应的视图函数

 1 def upload(request):
 2     print(request.FILES)
 3     obj = request.FILES.get('upload_img')
 4     path = os.path.join(settings.MEDIA_ROOT,'img/',obj.name)
 5     print(obj.name)
 6 
 7     with open(path,'wb') as f:
 8         for line in obj:
 9             f.write(line)
10     return HttpResponse('OK')

我们在settings.py中定义了一个静态文件的上传路径(/media/)为了管理的方便,我们在这个路径下新建一个img/文件夹来存放上传的图片文件。所以path就是项目的路径加上img后面是文件名。而request.FILE.get的值就是刚刚我们在模板中定义的filePostName

最后用常规的文件句柄把数据写入文件就行了。

上传完毕,就有下面的效果

 

 不要看标题上的上传错误,那个是定义出来的显示内容。主体内的OK是我们在视图中通过HttpResponse返回的字符串。然后在看看media文件夹内,是不是有了我们新上传的图片!

上传图片的显示

在常规操作中,我们一点上传图片的时候在文本编辑框中会出现我们上传的图片,这个操作就是需要我们视图中加一个返回的字典

 1 def upload(request):
 2     obj = request.FILES.get('upload_img')
 3     path = os.path.join(settings.MEDIA_ROOT,'img/',obj.name)
 4 
 5     with open(path,'wb') as f:
 6         for line in obj:
 7             f.write(line)
 8 
 9     ret = {
10         'error':0,
11         'url':'/media/img/'+obj.name,
12     }
13 
14     return HttpResponse(json.dumps(ret))

我们返回了一个字典,里面是一个状态字和一个url,这个url就是我们保存图片的路径,一定要注意,这个路径不是绝对路径!这样就完成了上传图片的显示

 

 

富文本编辑器里内容的保存

 新的文章保存,有一个字段比较重要:desc,我们在访问博客园的时候会看到有个这样的文章简介,就是标题下面那个

 

 

 这个简介就是把文章的内容截取了一个固定的长度,我们可以先用切片的方法来试一下

 1 def new_article(request,username):
 2     if request.method == 'POST':
 3         title = request.POST.get('title')
 4         content = request.POST.get('article_content')
 5 
 6         user = request.user
 7 
 8         desc = content[:150]
 9 
10         models.Article.objects.create(user=user,desc=desc)
11         print(title,content)
12 
13     return render(request,'new_article.html')

结果会是这种显示效果

 

 

 这是因为我们从页面的富文本编辑器传过来的字符串是一堆HTML形式的代码,字符串在做切片的时候是按照整个HTML文件作为一个大字符串来切片的,图示中的效果还算好,有些时候可能由于文章中的一些特定的标签在切片的时候被切掉,导致整个页面的效果崩溃。这就要用到一个新的库——BeautifulSoup。我们可以先通过下面的案例看一看这个beautifulsoup的作用是什么

from bs4 import BeautifulSoup
s = "<div>BeautifulSoup测试</div>"
soup = BeautifulSoup(s,'html.parser')
print('soup:\n',soup)
print('soup.text:\n',soup.text)

##########输出##########
soup:
 <div>BeautifulSoup测试</div>
soup.text:
 BeautifulSoup测试

我们可以通过soup.text获取到各种标签之间的字符串,就是页面上显示的内容。所以就可以把上面的那段视图代码修改成下面的方式

 1 from bs4 import BeautifulSoup
 2 def new_article(request,username):
 3     if request.method == 'POST':
 4         title = request.POST.get('title')
 5         content = request.POST.get('article_content')
 6 
 7         soup = BeautifulSoup(content,'html.parser')
 8         user = request.user
 9 
10         article_obj = models.Article.objects.create(user=user,desc=soup.text[0:150],title=title)
11         models.ArticleDetail.objects.create(content = content,article = article_obj)
12         print(title,content)
13 
14     return render(request,'new_article.html')

 

简易的XSS攻击预防

XSS攻击

 我们在前面提到过XSS攻击,这里可以再演示一下:如果我们新写的文章是这样的:

 

 注意,添加的字符串类型选择的是html,那么我们在打开这个文章页面的时候就会有个弹框弹出来

 

 这还是最简单的alert攻击,如果加上了死循环什么的浏览器就崩溃了。

看一下百度百科对XSS攻击的定义:

XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容

简单的XSS防御

有一个最简单暴力的方法就是对整个添加的字符串进行正则搜索,把定义的关键字率除掉,就可以了。但是BeautifulSoup给我们提供了一个功能,对指定的标签类型进行过滤

from bs4 import BeautifulSoup
s = "<div>BeautifulSoup测试</div> \
    <a href='http://127.0.0.1:8000'>a标签</a> \
        <script> \
        alert('XSS攻击测试')\
        </script>"

soup = BeautifulSoup(s,'html.parser')

for tag in soup.find_all():
    if tag.name in ['script','a']:
        tag.decompose()

print(soup)

##########输出值##########
<div>BeautifulSoup测试</div>  

可以看一下,我们可以用find_all的方式来拿到所有的tag,如果这个tag的样式是我们指定的(script和a标签),直接删掉。不是的就保留下来。

也就是我们直接定义一个非法的标签列表就行了。

但是还是有一点问题,像博客园一样,我们是可以插入程序段,里面包含了script的类型,那么用这个方式就被过滤掉了,留个悬念,以后再讲!

 

标签:文本编辑,request,beautifulsoup,博客,BeautifulSoup,content,soup,上传
来源: https://www.cnblogs.com/yinsedeyinse/p/13190812.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有