BBS - 後臺管理

1、添加文章

 

注:javascript

後臺管理頁面,應該有個新得 app

/blog/backend/ # 文章列表頁
/blog/add_article/ # 添加文章
# 後臺管理
re_path(r'backend/$', views.backend),
re_path(r'add_article/$', views.add_article),

2、文本編輯器

文本編輯器 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>

3、上傳文件

 

注意點: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))

4、提交文章 - BeautifulSoup 

 

 

總結: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: &lt;script&gt;alert(555)&lt;/script&gt;
轉爲:<script>alert(555)</script>,存到庫裏有問題的!
因此:
desc = soup.text[0:150]
desc = desc.replace('<', '&lt;').replace('>', '&gt;')

<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('<', '&lt;').replace('>', '&gt;')

        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)
models.py

5、BBS - 原始版 

https://github.com/alice-bj/cnblog_0git

相關文章
相關標籤/搜索