BBS项目补充知识(后台添加文章、修改文章功能完善)
1. 添加文章功能实现
# 修改 app02的views.py中 添加文章功能:
from django.http import JsonResponse
# 添加文章
def add_article(request):
# 1. 接收参数
if request.method == 'POST':
title = request.POST.get('title')
content = request.POST.get('content')
cate_id = request.POST.get('cate')
tag_list = request.POST.getlist('tags')
# 2. 验证参数
# 3. 切掉内容的前100字
desc = content[0:100]
# 4. 入库:article_obj返回是当前插入数据的对象,有了对象,就可以拿到当前文章的id
'''由于我们没有使用auth模块,所以,这里不能使用request.user,从session中手动获取'''
user_obj = models.UserInfo.objects.filter(pk=request.session.get('id')).first()
article_obj = models.Article.objects.create(title=title,
desc=desc,
content=content,
category_id=cate_id,
# blog=request.user.blog
blog_id=user_obj.blog_id
)
# 5. 处理标签id,操作第三张表,因为创建的第三张表是我们自己创建的,所以,add方法不能用了
# 因此,我们需要手动来操作表进行入库
'''由于操作数据库的次数过多,我们采用批量添加的形式,对数据库进行优化'''
article_obj_list = []
for i in tag_list:
tag_article_obj = models.Article2Tag(article_id=article_obj.pk, tag_id=i)
article_obj_list.append(tag_article_obj)
'''这样做的好处是:不管有多少个标签要入库,都是只操作一次数据库。'''
models.Article2Tag.objects.bulk_create(article_obj_list)
return redirect('/app02/article_list/')
# 查询出所有的分类列表
cate_list = models.Category.objects.all()
# 查询出所有的标签列表
tag_list = models.Tag.objects.all()
return render(request, 'backend/add_article.html', locals())
# 修改 add_article.html文件内 body内的 div标签:
<div class="container-fluid">
<div class="row">
<h1 class="text-center">添加文章</h1>
<div class="col-md-8 col-md-offset-2">
<form action="" method="post">
<div class="form-group">
<label for="title">文章标题</label>
<input type="text" id="title" name="title" class="form-control">
</div>
<div class="form-group">
<label for="title">文章内容</label>
<textarea id="editor_id" name="content" style="width:500px;height:600px;"></textarea>
</div>
<div class="form-group">
<label for="title">文章分类</label>
<select name="cate" id="" class="form-control">
{% for cate in cate_list %}
<option value="{{ cate.pk }}">{{ cate.title }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="title">文章标签</label>
{% for tag in tag_list %}
<input type="checkbox" name="tags" value="{{ tag.pk }}"> {{ tag.title }}
{% endfor %}
</div>
<input type="submit" class="btn btn-success" value="提交">
</form>
</div>
</div>
</div>
![image]()
![image]()
2. 完善数据库存储信息
"""
数据库中文章表保存的文章内容是原生的html标签
为了截取文章的前100个汉字,不能使用直接切片,该方法截取出来的是html标签的范围
如何解决?
我们需要借助bs4模块,这个模块在爬虫当中用的超级多,是爬虫中用的最大的一个模块之一
"""
# 修改 app02的views.py中 添加文章功能中 # 3. 切剪内容的前100字 4. 入库:
# 3. 切剪内容的前100字
# desc = content[0:100]
"""
为了截取文章的前100个汉字,不能使用该方法直接切片,截取出来的是html标签前100字符
# 如何解决?
我们需要借助bs4模块,这个模块在爬虫当中用的超级多,是爬虫中用的最大的一个模块之一
"""
# 使用该模块:bs4,
# 你还需要安装解析器模块
soup = BeautifulSoup(content, 'lxml')
tags = soup.find_all()
# 支持循环
for tag in tags:
'''针对xss攻击的核心:不能有script标签,如果没有这个标签,js代码就不会执行'''
print(tag.name)
# 判断是不是有script标签
if tag.name == 'script':
# 删除script标签
tag.decompose()
# desc = soup.text # 只拿文本内容
desc = soup.text[0:100] # 只拿文本内容
# 4. 入库:article_obj返回是当前插入数据的对象,有了对象,就可以拿到当前文章的id
'''由于我们没有使用auth模块,所以,这里不能使用request.user,从session中手动获取'''
user_obj = models.UserInfo.objects.filter(pk=request.session.get('id')).first()
article_obj = models.Article.objects.create(title=title,
desc=desc,
content=str(soup),
category_id=cate_id,
# blog=request.user.blog
blog_id=user_obj.blog_id
)
![image]()
![image]()
![image]()
3. 修改文章功能前端页面逻辑实现
# 修改app02下 article_list.html中修改a标签:
<a href="/app02/edit/article/?id={{ article.pk }}" target="_blank" class="btn btn-success">修改</a>
# app02下 添加路由:
# 修改文章
url(r'^edit/article/', views.edit_article),
# app02下 添加修改文章功能:
# 修改文章功能
def edit_article(request):
id = request.GET.get('id') # 文章id
article_obj = models.Article.objects.filter(pk=id).first()
# 第一步先找到当前文章所属的标签id
tag_ids_obj = models.Article2Tag.objects.filter(article_id=id).values_list('tag_id')
tag_ids = [] #
for tag in tag_ids_obj:
tag_id = tag[0]
tag_ids.append(tag_id)
# 查询出所有的分类列表
cate_list = models.Category.objects.all()
# 查询出所有的标签列表
tag_list = models.Tag.objects.all()
return render(request, 'backend/edit_article.html', locals())
# 新建edit_article.html文件:
"""将add_article.html内容复制过去并做部分修改即可 文章分类 文章标签 两个div即可"""
<div class="form-group">
<label for="title">文章分类</label>
<select name="cate" id="" class="form-control">
{% for cate in cate_list %}
{% if article_obj.category_id == cate.pk %}
<option value="{{ cate.pk }}" selected>{{ cate.title }}</option>
{% else %}
<option value="{{ cate.pk }}">{{ cate.title }}</option>
{% endif %}
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="title">文章标签</label>
{% for tag in tag_list %}
{% if tag.pk in tag_ids %}
<input type="checkbox" name="tags" checked value="{{ tag.pk }}"> {{ tag.title }}
{% else %}
<input type="checkbox" name="tags" value="{{ tag.pk }}"> {{ tag.title }}
{% endif %}
{% endfor %}
</div>
![image]()
4. 富文本编辑器上传图片
# 在edit_article.html文件中 修改 script标签内容 添加uploadJson:
resizeType: 0,
themeType: 'simple',
uploadJson:'/app02/upload_img/'
});
});
</script>
# 在项目总路由中添加开放路径:
from django.views.static import serve
from django.conf import settings
# 开放路径
url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),
# 在app02路由中添加:
# 编辑器上传图片
url(r'^upload_img/', views.upload_img),
# app02下 views.py中 添加上传图片功能:
from django.http import JsonResponse
from django.conf import settings
import os
# 上传图片功能
def upload_img(request):
'''
//成功时
{
"error" : 0,
"url" : "http://www.example.com/path/to/file.ext"
}
//失败时
{
"error" : 1,
"message" : "错误信息"
}
:param request:
:return:
'''
back_dic = {
"error": 0,
"url": ""
}
if request.method == 'POST':
file_obj = request.FILES.get('imgFile')
# 拼接要上传的文件路径
file_dir = os.path.join(settings.BASE_DIR, 'media', 'article_img')
if not os.path.exists(file_dir):
os.mkdir(file_dir)
'''
解决文件名被覆盖问题
1. 截取图片的后缀名
2. 生成随机字符串
3. 随机字符串 + 后缀名
'''
# 拼接文件的完整路径
file_path = os.path.join(file_dir, file_obj.name)
# /media/article_img/123.png
# 上传文件
with open(file_path, 'wb') as f:
for line in file_obj:
f.write(line)
back_dic['url'] = '/media/article_img/%s' % file_obj.name
return JsonResponse(back_dic)
![image]()
![image]()