博客-富文本編輯器
在這一節使用的是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 樣式文件
看附件
效果圖
上傳圖片
保存之後在頁面中展示會如下, 樣式會亂
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標籤的文章
最終顯示就正常了
過濾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")