bbs项目(部分讲解)


文章评论业务完善

提交评论
	评论框里面的内容会清空 然后页面会有一个临时评论样式出现 页面刷新才会出现评论楼样式

研究子评论特性
	每个评论右侧都应该有回复按钮 点击就可以填写子评论
	点击回复按钮具体动作:评论框中自动添加@+评论的人名并换行 聚焦
		如何区分不同的回复按钮所对应的用户名
  			利用标签可以自定义属性直接携带对应的评论用户名即可
 
提交根评论和子评论点击的是同一个按钮 两者的区别与联系是什么
	其实根评论和子评论的唯一区别就是是否有父评论的主键值
		如何区分不同的回复按钮所对应的评论主键值
   			利用标签可以自定义属性直接携带对应的评论主键值即可
        
点击回复按钮发送子评论 页面不刷新的情况下 后续的评论全部成了子评论
	原因是全局变量parentId没有清空导致的 每次提交评论都应该清空一下
 
针对子评论内中的@用户名换行 理论上不属于用户评论的内容 不应该记录到数据库
	前端可以剔除 也可以在后端剔除
  
针对子评论的渲染 应该动态判断是否是子评论 如果是应该加上评论的目标用户名

注意:针对评论的渲染也可以分页 也可以做根评论与子评论的集合操作(分类)

后台管理

base.html

    

文章展示

{% block crticle %} {% endblock %}
{% block add %} {% endblock %}

index.html

{% extends 'backend/base.html' %}
{% block title %}
    后台管理
{% endblock %}

{% block crticle %}
    
{% for article in article_list %} {% endfor %}
编号 标题 发布时间 评论数 操作 操作
{{ forloop.counter }} {{ article.title }}/ {{ article.create_time|date:'Y-m-d H:i' }} {{ article.comment_num }} 删除 修改
{% endblock %}

新建文章

前端模板

{% extends 'backend/base.html' %}

{% block link %}
    
    
{% endblock %}

{% block title %}
    添加文章
{% endblock %}

{% block add %}
    

添加随笔

{% csrf_token %}
{% endblock %} {% block js %} // 使用富文本编辑器 {% endblock %}
def add(request):
    if request.method == 'GET':
        tag_list = Tag.objects.filter(blog=request.user.blog)
        classify_list = Classify.objects.filter(blog=request.user.blog)
        return render(request, 'backend/add.html', context={'tag_list': tag_list, 'classify_list': classify_list})
    title = request.POST.get('title')
    content = request.POST.get('content')
    # BeautifulSoup第一个参数是html内容,第二个参数:使用的解析器
    bs = BeautifulSoup(content, features='html.parser')
    # 截取html文本,将空格和换行替换成空,并截取70个字符
    desc = bs.text.replace(' ', '').replace('\n', '')[:70] + '...'
    # 剔除script标签
    script_list = bs.findAll('script')
    for i in script_list:
        i.decompose()  # 将每个script标签删除
    classify = request.POST.get('category')
    tag = request.POST.getlist('tag')  # 这是多对多的
    res = Article.objects.create(title=title, content=str(bs), desc=desc, classify_id=classify, blog=request.user.blog)
    # 多对多添加外键关系
    res.tag.add(*tag)
    return redirect('/backend/')

富文本编辑器图片处理,查看官方文档

# 文章图片处理
# 需要处理csrf 可已经用掉这个接口的csrf

@csrf_exempt  # 免除校验
def put_img(request):
    img = request.FILES.get('imgFile')
    path = os.path.join(settings.MEDIA_ROOT, 'upload', img.name)
    with open(path, 'wb') as f:
        for i in img:
            f.write(i)
    return JsonResponse({
        "error": 0,
        "url": f"http://127.0.0.1:8000/media/upload/{img.name}"
    })

处理xss攻击

xss跨站脚本,在内容中存script脚本,前端渲染时使用了safe,如果存在script脚本,就会执行。解决方案。富文本编辑器在输入代码块时会自动将尖括号转换成对应的字符,只需在后端将恶意的script清除即可

  1. 页面简易搭建
  2. 文章内容区富文本编辑器的使用
    课下可以自行查找更多的富文本编辑器使用
  3. 添加文章需要注意的问题
    文章简介不应该有标签存在
    文章内容不允许编辑script脚本(XSS攻击)

涉及到html相关内容的处理 可以借助于爬虫相关模块
bs4

需要使用beautifulsoup4模块

-pip3 install beautifulsoup4
-删除script标签
 soup = BeautifulSoup(content, 'html.parser')
 script_list=soup.findAll('script') # 搜索到html中所有的script标签
 for script in script_list:
     script.decompose() # 把搜到的script标签一个个删除

首页用户信息展示

用户登陆后展示用户名和和管理选项按钮


                    {% if request.user.is_authenticated %}
                        
  • {{ request.user.username }}
  • {% else %} 登录 注册 {% endif %}

    退出后台

    # 退出登录
    def login_out(request):
        logout(request)  # request.session.flush() 清除掉session和cookie
        return redirect('/')
    

    修改头像

    {% extends 'backend/base.html' %}
    
    {% block title %}
        修改头像
    {% endblock %}
    
    {% block add %}
        
    {% csrf_token %}

    修改头像

    {% endblock %} {% block js %} {% endblock %}
    # 修改头像
    def alter_icon(request):
        if request.method == "GET":
            # 需要当前用户头像
            icon = request.user.icon
            return render(request, 'backend/alter_icon.html', context={'icon': icon})
        icon = request.FILES.get('icon')
        request.user.icon = icon
        request.user.save()
        return redirect('/')
    

    修改密码

    {% extends 'backend/base.html' %}
    
    {% block title %}
        修改密码
    {% endblock %}
    
    {% block add %}
        
    {% csrf_token %}
    {{ error }}
    {% endblock %}
    def set_pwd(request):
        if request.method == 'GET':
            return render(request, 'backend/set_pwd.html')
        old_password = request.POST.get('old_password')
        new_password = request.POST.get('new_password')
        re_password = request.POST.get('re_password')
        if request.user.check_password(old_password):
            if new_password == re_password:
                request.user.set_password(new_password)
                request.user.save()
                # 退出当前登录 跳转至登录
                login_out(request)
                return redirect(to='/login/')
            return render(request, 'backend/set_pwd.html', context={'error': '两次密码不一致'})
        return render(request, 'backend/set_pwd.html', context={'error': '原密码不一致'})
    

    修改文章

    {% extends 'backend/base.html' %}
    
    {% block link %}
        
        
    {% endblock %}
    
    {% block title %}
        修改文章
    {% endblock %}
    
    {% block add %}
        

    修改文章

    {% csrf_token %}
    {% endblock %} {% block js %} {% endblock %}
    def alter_article(request):
        pk = request.GET.get('pk')
        # 需要当前文章 当前用户的分类和标签
        if request.method == 'GET':
            article = Article.objects.filter(pk=pk).first()
            classify_list = Classify.objects.filter(blog=request.user.blog)
            tag_list = Tag.objects.filter(blog=request.user.blog)
            return render(request, 'backend/alter_article.html',
                          context={'article': article, 'classify_list': classify_list, 'tag_list': tag_list})
        # post请求 修改文章
        title = request.POST.get('title')
        content = request.POST.get('content')
        # BeautifulSoup第一个参数是html内容,第二个参数:使用的解析器
        bs = BeautifulSoup(content, features='html.parser')
        # 截取html文本,将空格和换行替换成空,并截取70个字符
        desc = bs.text.replace(' ', '').replace('\n', '')[:70] + '...'
        # 剔除script标签
        script_list = bs.findAll('script')
        for i in script_list:
            i.decompose()  # 将每个script标签删除
        classify = request.POST.get('category')
        tag = request.POST.getlist('tag')  # 这是多对多的
        article = Article.objects.filter(pk=request.GET.get('pk'))  # 必须是一个queryset
        # 还需要将该文章的评论点赞点踩一起更新
        up_num = Article.objects.filter(pk=pk).first().up_num
        down_num = Article.objects.filter(pk=pk).first().down_num
        comment_num = Article.objects.filter(pk=pk).first().comment_num
        with transaction.atomic():
            article.update(title=title, desc=desc, classify_id=classify, content=str(bs), blog=request.user.blog,
                           up_num=up_num, down_num=down_num, comment_num=comment_num)
            article.first().save()
            # 多对多关系添加
            article.first().tag.set(tag)
        return redirect(f'/{request.user.username}/articles/{pk}')
    

    相关