python_day22_Django-7 (博客-富文本編輯器)

博客-富文本編輯器

  在這一節使用的是kindeditor富文本編輯器, 下載地址 官方文檔, 官網只更新到了4.1.11, github更新到了4.1.12, 往下直接就是代碼示例

1、settings.py

使用自己定義的用戶模塊
AUTH_USER_MODEL = "app01.UserInfo"

# 靜態文件目錄, 可以放js css image之類的文件
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static")
]

# 用戶上傳的都叫media文件
MEDIA_URL = "/media/"

# media配置,用戶上傳的文件都默認放在這個文件夾下
MEDIA_ROOT = os.path.join(BASE_DIR, "media")

2、urls.py

from django.urls import path, re_path, include
urlpatterns = [
    path("blog/", include("app01.urls"), name="blog"),
]

3、創建應用

python manage startapp blog

settings.py文件中註冊應用

INSTALLED_APPS = [
        # 最後新增這一行
    'app01.apps.App01Config',
]

blog應用中創建urls.py文件

from django.urls import path, re_path, include
from app01 import views
app_name = "blog"

urlpatterns = [
    # 添加文件
    re_path("add_article/", views.add_article, name="add_article"),
        # 上傳圖片函數
    re_path("comment_article/", views.comment_article, name="comment_article"),

]

4、表結構

  來源老男孩的課程

from django.db import models

# Create your models here.

from django.contrib.auth.models import AbstractUser

class UserInfo(AbstractUser):
    """
    用戶信息表
    """
    nid = models.AutoField(primary_key=True)
    portrait = models.FileField(upload_to="images/", default="", verbose_name="頭像")
    create_time = models.DateTimeField(auto_now_add=True)

    blog = models.OneToOneField(to="Blog", to_field="nid", null=True, on_delete=models.CASCADE)

    def __str__(self):
        return self.username

    class Meta:
        verbose_name = "用戶"
        verbose_name_plural = verbose_name

class Blog(models.Model):
    """
    博客信息
    """
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=64)  # 個人博客標題
    site = models.CharField(max_length=32, unique=True)  # 個人博客後綴
    theme = models.CharField(max_length=32)  # 博客主題

    def __str__(self):
        return self.title

    class Meta:
        verbose_name = "blog站點"
        verbose_name_plural = verbose_name

class Category(models.Model):
    """
    個人博客文章分類
    """
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)  # 分類標題
    blog = models.ForeignKey(to="Blog", to_field="nid", on_delete=models.CASCADE)  # 外鍵關聯博客,一個博客站點可以有多個分類

    def __str__(self):
        return self.title

    class Meta:
        verbose_name = "文章分類"
        verbose_name_plural = verbose_name

class Tag(models.Model):
    """
    標籤
    """
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)  # 標籤名
    blog = models.ForeignKey(to="Blog", to_field="nid", on_delete=models.CASCADE)  # 所屬博客

    def __str__(self):
        return self.title

    class Meta:
        verbose_name = "標籤"
        verbose_name_plural = verbose_name

class Article(models.Model):
    """
    文章
    """
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=50, verbose_name="文章標題")  # 文章標題
    desc = models.CharField(max_length=255)  # 文章描述
    create_time = models.DateTimeField(auto_now_add=True)  # 創建時間

    # 評論數
    comment_count = models.IntegerField(verbose_name="評論數", default=0)
    # 點贊數
    up_count = models.IntegerField(verbose_name="點贊數", default=0)
    # 踩
    down_count = models.IntegerField(verbose_name="踩數", default=0)

    category = models.ForeignKey(to="Category", to_field="nid", null=True, on_delete=models.CASCADE)
    user = models.ForeignKey(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 Meta:
        verbose_name = "文章"
        verbose_name_plural = verbose_name

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)

    class Meta:
        verbose_name = "文章詳情"
        verbose_name_plural = verbose_name

class Article2Tag(models.Model):
    """
    文章和標籤的多對多關係表
    """
    nid = models.AutoField(primary_key=True)
    article = models.ForeignKey(to="Article", to_field="nid", on_delete=models.CASCADE)
    tag = models.ForeignKey(to="Tag", to_field="nid", on_delete=models.CASCADE)

    class Meta:
        unique_together = (("article", "tag"),)
        verbose_name = "文章-標籤"
        verbose_name_plural = verbose_name

    def __str__(self):
        return "{} - {}".format(self.article.title, self.tag)

class ArticleUpDown(models.Model):
    """
    點贊表
    """
    nid = models.AutoField(primary_key=True)
    user = models.ForeignKey(to="UserInfo", null=True, on_delete=models.CASCADE)
    article = models.ForeignKey(to="Article", null=True, on_delete=models.CASCADE)
    is_up = models.BooleanField(default=True)

    class Meta:
        unique_together = (("article", "user"),)
        verbose_name = "文章點贊"
        verbose_name_plural = verbose_name

class Comment(models.Model):
    """
    評論表
    """
    nid = models.AutoField(primary_key=True)
    article = models.ForeignKey(to="Article", to_field="nid", on_delete=models.CASCADE)
    user = models.ForeignKey(to="UserInfo", to_field="nid", on_delete=models.CASCADE)
    content = models.CharField(max_length=255)  # 評論內容
    create_time = models.DateTimeField(auto_now_add=True)
    parent_comment = models.ForeignKey("self", null=True, blank=True, on_delete=models.CASCADE)  # blank=True 在django admin裏面可以不填

    def __str__(self):
        return self.content

    class Meta:
        verbose_name = "評論"
        verbose_name_plural = verbose_name

遷移數據  
python manage makemigrations
python manage migrate
每次修改完modle.py文件都需要執行這兩行遷移數據命令, 執行完之後可以應用中的migrations包中看到執行的sql語句

5、views.py

視圖函數
def add_article(request):
    print(request.POST)
    if request.method == "POST":
        title = request.POST.get("title")
        content = request.POST.get("textarea_content")
        user = request.user
        article_obj = Article.objects.create(user=user, title=title, desc=content[0:50])
        ArticleDetail.objects.create(content=content, article=article_obj)
        return HttpResponse("添加成功")

    return render(request, "blog/add_article.html")

def comment_article(request):
    print(request.FILES)
    filename = request.FILES.get("image_obj")
    path = os.path.join(settings.MEDIA_ROOT, "user_upload", filename.name)
    with open(path, "wb") as F:
        for line in filename:
            F.write(line)
    urls = "/media/user_upload/{0}".format(filename.name)
    res = {
        "error": 0,
        "url": urls,
    }

    '''
    //成功時 http://kindeditor.net/docs/upload.html
    {
            "error" : 0,
            "url" : "http://www.example.com/path/to/file.ext"
    }
    //失敗時
    {
            "error" : 1,
            "message" : "錯誤信息"
    }

    '''
    return JsonResponse(res)

6、add_article.html

在templaters中新建blog文件夾 創建add_article.html文件
{% extends 'base.html' %}
{% load static %}

{% block content %}
    <div class="container">
        <div class="row">
            <div class="col-md-2"></div>
            <div class="col-md-10">
                <div id="Editor_Edit">
                    <div id="Editor_Edit_Header" class="CollapsibleTitle">
                        <span id="Editor_Edit_headerTitle">添加文章</span>
                    </div>
                    <form action="" method="post">
                        <div>
                            <label for="">標題</label>
                            <input type="text" class="form-control" style="height: 30px;" name="title">
                        </div>
                        <div class="Editor_content">
                            <p>內容(kindeditor編輯器,點擊上傳圖片,可批量上傳)</p>
                            <textarea cols="80px" rows="10px" name="textarea_content" id="editor_id"></textarea>
                            <input type="submit" value="提交文章">
                        </div>
                        {% csrf_token %}
                    </form>
                </div>
            </div>
        </div>
    </div>

    <script charset="utf-8" src="{% static 'kindeditor/kindeditor-all.js' %}"></script>
    <script src="{% static 'jquery-3.3.1.js' %}"></script>
    <script>
        KindEditor.ready(function (K) {
            window.editor = K.create('#editor_id', {
                width: '100%',
                height: "400px",
                resizeType: 1,
                uploadJson: "{% url 'blog:comment_article' %}",
                extraFileUploadParams: {
                    csrfmiddlewaretoken: $('[name="csrfmiddlewaretoken"]').val()
                },
                filePostName: "image_obj",
            });
        });
    </script>

{% endblock %}

base.html文件
index.html用於主頁展示
public.css 樣式文件
看附件

效果圖
python_day22_Django-7 (博客-富文本編輯器)

上傳圖片

python_day22_Django-7 (博客-富文本編輯器)

保存之後在頁面中展示會如下, 樣式會亂
python_day22_Django-7 (博客-富文本編輯器)

7、引入beautifulsoup4

    安裝 pip install beautifulsoup4

修改視圖函數 views.py
from bs4 import BeautifulSoup

def add_article(request):
    print(request.POST)
    if request.method == "POST":
        title = request.POST.get("title")
        content = request.POST.get("textarea_content")
        user = request.user
        bs = BeautifulSoup(content, "html.parser")  # 將html解析成字符串
        desc = bs.text[0:50]+"...."   # 只要前50個字符並且加上...
        article_obj = Article.objects.create(user=user, title=title, desc=desc)
        ArticleDetail.objects.create(content=content, article=article_obj)
        return HttpResponse("添加成功")

    return render(request, "blog/add_article.html")

重新添加帶有html標籤的文章

最終顯示就正常了
python_day22_Django-7 (博客-富文本編輯器)

過濾html標籤
def add_article(request):
    print(request.POST)
    if request.method == "POST":
        title = request.POST.get("title")
        content = request.POST.get("textarea_content")
        user = request.user
        bs = BeautifulSoup(content, "html.parser")  # 將html解析成字符串
        desc = bs.text[0:50]+"...."   # 只要前50個字符並且加上...

        # 查看所有的html標籤
        for line in bs.find_all():
            # 如果名稱中包含script標籤或者其它,那麼就刪除它
            if line.name in ["script"]:
                line.decompose()

        article_obj = Article.objects.create(user=user, title=title, desc=desc)
        # 將刪除標籤之後的文本保存到數據庫中
        ArticleDetail.objects.create(content=str(bs), article=article_obj)
        return HttpResponse("添加成功")

    return render(request, "blog/add_article.html")
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章