注:javascript
後臺管理頁面,應該有個新得 app
/blog/backend/ # 文章列表頁
/blog/add_article/ # 添加文章
# 後臺管理
re_path(r'backend/$', views.backend),
re_path(r'add_article/$', views.add_article),
文本編輯器 kindeditor 本質上就是(css+js)
官網:
http://kindeditor.net/demo.php
http://kindeditor.net/doc.php
使用:
kindeditor
<script src="/static/kindeditor/kindeditor-all.js"></script>
<textarea name="article_con" id="article_box" cols="30" rows="10"></textarea>
KindEditor.ready(function (k) {
window.editor = k.create('#article_box')
...
})
KindEditor會覆蓋textarea, 注意 id
初始化 參數
http://kindeditor.net/docs/option.html
add_article.html php
注意:kindeditor 參數配置css
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>add_article</title> <style type="text/css"> *{padding: 0;margin: 0} .header{ width: 100%; height: 60px;background-color: green} .content{ padding-top: 30px;} </style> </head> <body> <div class="header"> </div> <div class="content"> <form action="" method="post"> {% csrf_token %} <div class="title"> 標題: <input type="text" name="title" > </div> <div> 內容:<br> <textarea name="article_con" id="article_box" cols="30" rows="10"></textarea> </div> <input type="submit"> </form> </div> {% csrf_token %} <script src="/static/js/jquery-3.2.1.min.js"></script> <script src="/static/kindeditor/kindeditor-all.js"></script> <script charset="utf-8" src="/static/kindeditor/lang/zh-CN.js"></script> <script type="text/javascript"> KindEditor.ready(function (k) { // 將 本身寫得 textarea id=article_box 覆蓋 window.editor = k.create('#article_box',{ width:800, height:400, items:[ // 留可選得!! 'source', '|', 'undo', 'redo', '|', 'preview', 'print', 'template', 'code', 'cut', 'copy', 'paste', 'plainpaste', 'wordpaste', '|', 'justifyleft', 'justifycenter', 'justifyright', 'justifyfull', 'insertorderedlist', 'insertunorderedlist', 'indent', 'outdent', 'subscript', 'superscript', 'clearhtml', 'quickformat', 'selectall', '|', 'fullscreen', '/', 'formatblock', 'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold', 'italic', 'underline', 'strikethrough', 'lineheight', 'removeformat', '|', 'image', 'multiimage', 'flash', 'media', 'insertfile', 'table', 'hr', 'emoticons', 'baidumap', 'pagebreak', 'anchor', 'link', 'unlink', '|', 'about' ], resizeType:0, uploadJson:'upload_img/', extraFileUploadParams:{"csrfmiddlewaretoken":$('input[name=csrfmiddlewaretoken]').val()}, filePostName:'img' }) }) </script> </body> </html>
注意點:html
以前學過:form ajax
此次是:編輯器發文件:實質是 ajax的post
注意:
1.參數配置
uploadJson:'upload_img/', # 得是相對路徑,不然會報錯!
extraFileUploadParams:{"csrfmiddlewaretoken":$('input[name=csrfmiddlewaretoken]').val()},
filePostName:'img'
2.url
re_path(r'upload_img/', views.upload_img),
3.用戶文件存放 /media/article_imgs/...
img_obj = request.FILES.get('img')
# MEDIA_ROOT = os.path.join(BASE_DIR,'blog','media')
media_path = settings.MEDIA_ROOT
path = os.path.join(media_path,'article_imgs',img_obj.name)
4.寫文件
with open(path,'wb') as f:
for line in img_obj:
f.write(line)
5.返回json
res = {
"url":"/media/article_imgs/"+img_obj.name,
"error":0
}
return HttpResponse(json.dumps(res))
code:java
from cnblog import settings import os import json def upload_img(request): print('files:',request.FILES) # files 才能拿到文件 # <MultiValueDict: {'imgFile': [<InMemoryUploadedFile: lufei.jpg (image/jpeg)>]}> # 能夠本身定義 文件名!! filePostName:'img' # < MultiValueDict: {'img': [ < InMemoryUploadedFile: lufei.jpg(image / jpeg) >]} > img_obj = request.FILES.get('img') # MEDIA_ROOT = os.path.join(BASE_DIR,'blog','media') media_path = settings.MEDIA_ROOT path = os.path.join(media_path,'article_imgs',img_obj.name) with open(path,'wb') as f: for line in img_obj: f.write(line) res = { "url":"/media/article_imgs/"+img_obj.name, "error":0 } return HttpResponse(json.dumps(res))
總結:python
Article:
nid, title, desc, create_time, comment_count, up_count, down_count, category, user, tags,
ArticleDetail:
nid,content,article
注意點:
title = request.POST.get('title')
article_con = request.POST.get('article_con')
0.防止XSS攻擊:引入 (BeautifulSoup)
https://www.cnblogs.com/yuanchenqi/articles/7617280.html
http://beautifulsoup.readthedocs.io/zh_CN/latest/
簡單來講,Beautiful Soup是python的一個庫,最主要的功能是從網頁解析數據。
。。。詳細使用。。。
pip3 install beautifulsoup4
from bs4 import BeautifulSoup
soup = BeautifulSoup(article_con,'html.parser')
# 過濾 script
for tag in soup.find_all():
if tag.name == 'script':
tag.decompose() # 刪除了全部的script標籤及內容
獲取desc
1.
if desc = article_con[0:150]
會有問題:article_con 內容中含有標籤,截取會截不全,致使有的標籤沒有閉合,樣式錯亂!
2.
圖片代碼不截,只截文本 soup.text[0:150] 會有一點問題:
引入:beautifulsoup 針對標籤,字符串,作過濾查詢。
soup = BeautifulSoup(article_con,'html.parser')
desc = soup.text[0:150]
but: 有一點問題 soup.text # text 把轉義的字符又返回去了!!
eg: <script>alert(555)</script>
轉爲:<script>alert(555)</script>,存到庫裏有問題的!
因此:
desc = soup.text[0:150]
desc = desc.replace('<', '<').replace('>', '>')
<p>{{ article.desc|safe }}</p>3.soup.prettify()
code:jquery
def add_article(request): if request.method == 'POST': title = request.POST.get('title') article_con = request.POST.get('article_con') from bs4 import BeautifulSoup soup = BeautifulSoup(article_con, 'html.parser') print('text1:', soup.text) # text 把 轉義的字符又返回去了!! # 過濾 script for tag in soup.find_all(): if tag.name == 'script': tag.decompose() # 刪除了全部的script標籤 desc = soup.text[0:150] desc = desc.replace('<', '<').replace('>', '>') article_obj = Article.objects.create(title=title, desc=desc,user=request.user) # soup.prettify() == str(soup) ArticleDetail.objects.create(content=soup.prettify(),article=article_obj) return HttpResponse('提交成功') else: return render(request, 'add_article.html')
class Article(models.Model): """ 文章信息 """ nid = models.AutoField(primary_key=True) title = models.CharField(max_length=50, verbose_name='文章標題') desc = models.CharField(max_length=255, verbose_name='文章描述') create_time = models.DateTimeField(verbose_name='建立時間',auto_now_add=True) comment_count = models.IntegerField(default=0) # 爲了查詢時,效率高! up_count = models.IntegerField(default=0) down_count = models.IntegerField(default=0) category = models.ForeignKey(to='Category', to_field='nid', null=True, on_delete=models.CASCADE) user = models.ForeignKey(verbose_name='做者', to='UserInfo', to_field='nid', on_delete=models.CASCADE) tags = models.ManyToManyField( to='Tag', through='Article2Tag', through_fields=('article','tag'), ) def __str__(self): return self.title class ArticleDetail(models.Model): """ 文章詳細表 """ nid = models.AutoField(primary_key=True) content = models.TextField() article = models.OneToOneField(to='Article', to_field='nid', on_delete=models.CASCADE)