设为首页 收藏本站
查看: 455|回复: 1

BBS后台页搭建、富文本编辑上传文件、XSS攻击、修改头像

[复制链接]
累计签到:528 天
连续签到:1 天
发表于 2022-10-30 10:28:07 | 显示全部楼层 |阅读模式
# 后台管理
所有文件夹都可以根据功能再细化,你还可以继续创建文件夹分类处理
    templates文件夹
        backend文件夹
        应用1文件夹
        应用2文件夹
第一步是实现:    1、在static文件夹下单独创建一个backend文件夹统一管理关于后台的html页面    2、分为base.html,backend.html、add_article.html继承base做修改,
接下来看主要的base.html代码,因为很多地方要用到这个公共的模板<div class="container-fluid">
    <div class="row">
        <div class="col-md-2">        <div class="col-md-10">
  div>
  <!-- Nav tabs -->
  <ul class="nav nav-tabs" role="tablist">
    <li role="presentation" class="active"><a href="#home" aria-controls="home" role="tab" data-toggle="tab">文章</a></li>
    <li role="presentation"><a href="#profile" aria-controls="profile" role="tab" data-toggle="tab">随笔</a></li>
    <li role="presentation"><a href="#messages" aria-controls="messages" role="tab" data-toggle="tab">文件</a></li>
    <li role="presentation"><a href="#settings" aria-controls="settings" role="tab" data-toggle="tab">设置</a></li>
  </ul>

  <!-- Tab panes -->
  <div class="tab-content">
    <div role="tabpanel" class="tab-pane active" id="home">
        {% block article %}
            文章界面
        {% endblock %}
    </div>
    <div role="tabpanel" class="tab-pane" id="profile">
        {% block suibi %}
            随笔界面
        {% endblock %}

    </div>
    <div role="tabpanel" class="tab-pane" id="messages">
        {% block file %}
            文件界面
        {% endblock %}

    </div>
    <div role="tabpanel" class="tab-pane" id="settings">
        {% block set %}
            设置界面
        {% endblock %}
    </div>
  </div>
2、 backend.html管理页怎么搭建(继承base.html修改内容部分){% extends 'backend/backend_base.html' %}


{% block article %}
{#    展示当前用户所有的文章#}
    <table class="table table-hover table-striped">
        <thead>
            <tr>
                <th>标题</th>
                <th>点赞数</th>
                <th>评论数</th>
                <th>操作</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            {% for article in page_queryset %}
                <tr>
                    <td><a href="/{{ article.blog.userinfo.username }}/article/{{ article.pk }}/">{{ article.title }}</a></td>
                    <td>{{ article.up_num }}</td>
                    <td>{{ article.comment_num }}</td>
                    <td><a href="">编辑</a></td>
                    <td><a href="">删除</a></td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
    <div class="pull-right">
        {{ page_obj.page_html|safe }}
    </div>
{% endblock %}
</div>
[backend后端代码]from app01.utils.mypage import Pagination
@login_required
def backend(request):
    # 获取当前用户对象所有的文章展示到页面
    article_list = models.Article.objects.filter(blog=request.user.blog)

    page_obj = Pagination(current_page=request.GET.get('page',1),all_count=article_list.count())
    page_queryset = article_list[page_obj.start:page_obj.end]
    return render(request,'backend/backend.html',locals())
第二步:如何是富文本编辑器和文章的添加、防止XSS攻击</div>add_article.html搭建{% extends 'backend/backend_base.html' %}


{% block article %}
    <h3>添加文章</h3>
    {#    直接利用form表单提交数据#}
    <form action="" method="post">
        {% csrf_token %}
        <p>标题</p>
        <div>
            <input type="text" name="title" class="form-control">
        </div>
        <p>内容</p>
        <div>
            <textarea name="content" id="id_content" cols="30" rows="10"></textarea>
        </div>
        <p>分类</p>
        <div>
            {% for category in category_list %}
                <input type="radio" value="{{ category.pk }}" name="category">{{ category.name }}
            {% endfor %}

        </div>
        <p>标签</p>
        <div>
            {% for tag in tag_list %}
                <input type="checkbox" value="{{ tag.pk }}" name="tag">{{ tag.name }}
            {% endfor %}
        </div>
        <input type="submit" class="btn btn-danger">
    </form>
{% endblock %}

{% block js %}
    {% load static %}
    <script charset="utf-8" src="{% static 'kindeditor/kindeditor-all-min.js' %}"></script>
    <script>
        KindEditor.ready(function (K) {
            window.editor = K.create('#id_content', {
                width: '100%',
                height: '600px',
                resizeType:1,
                uploadJson : '/upload_image/',  // 上传图片的后端提交路径
                extraFileUploadParams : {
                        'csrfmiddlewaretoken':'{{ csrf_token }}'
                }
            });
        });
    </script>
{% endblock %}
[后端代码]关于添加文章、XSS攻击的from bs4 import BeautifulSoup
@login_required
def add_article(request):
    if request.method == 'POST':
        title = request.POST.get('title')
        content = request.POST.get('content')
        category_id = request.POST.get("category")
        tag_id_list = request.POST.getlist('tag')
        # 模块使用
        soup = BeautifulSoup(content,'html.parser')

        tags = soup.find_all()
        # 获取所有的标签
        for tag in tags:
            # print(tag.name)  # 获取页面所有的标签
            # 针对script标签 直接删除
            if tag.name == 'script':
                # 删除标签
                tag.decompose()
        # 文章简介
        # 1 先简单暴力的直接切去content 150个字符
        # desc = content[0:150]
        # 2 截取文本150
        desc = soup.text[0:150]
        article_obj = models.Article.objects.create(
            title=title,
            content=str(soup),
            desc=desc,
            category_id=category_id,
            blog=request.user.blog
        )
        # 文章和标签的关系表 是我们自己创建的 没法使用add set remove clear方法
        # 自己去操作关系表   一次性可能需要创建多条数据      批量插入bulk_create()
        article_obj_list = []
        for i in tag_id_list:
            tag_article_obj = models.Article2Tag(article=article_obj,tag_id=i)
            article_obj_list.append(tag_article_obj)
        # 批量插入数据
        models.Article2Tag.objects.bulk_create(article_obj_list)
        # 跳转到后台管理文章展示页
        return redirect('/backend/')
    category_list = models.Category.objects.filter(blog=request.user.blog)
    tag_list = models.Tag.objects.filter(blog=request.user.blog)
    return render(request,'backend/add_article.html',locals())关于传文件(图片)格式存储和接口处理import os
from BBS14 import settings
def upload_image(request):
    """
         //成功时
        {
                "error" : 0,
                "url" : "http://www.example.com/path/to/file.ext"
        }
        //失败时
        {
                "error" : 1,
                "message" : "错误信息"
        }
    :param request:
    :return:
    """
    back_dic = {'error': 0, }  # 先提前定义返回给编辑器的数据格式

    # 用户写文章上传的图片 也算静态资源 也应该防盗media文件夹下

    if request.method == "POST":
        # 获取用户上传的图片对象
        # print(request.FILES)  # 打印看到了健固定叫imgFile
        file_obj = request.FILES.get('imgFile')
        # 手动拼接存储文件的路径
        file_dir = os.path.join(settings.BASE_DIR,'media','article_img')
        # 优化操作 先判断当前文件夹是否存在 不存在 自动创建
        if not os.path.isdir(file_dir):
            os.mkdir(file_dir)  # 创建一层目录结构  article_img
        # 拼接图片的完整路径
        file_path = os.path.join(file_dir,file_obj.name)
        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)

第三步:修改头像> 前端代码{% extends 'base.html' %}


{% block content %}
    <h3 class="text-center">修改头像</h3>
    <form action="" method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <p>
            原头像:
            <img src="/media/{{ request.user.avatar }}" alt="">
        </p>
        <p>

            <label for="myfile">新头像:
                        {% load static %}
            <img src="{% static 'img/default.png' %}" id='myimg' alt="" width="100" style="margin-left: 10px">
                    </label>
            <input type="file" id="myfile" name="avatar" style="display: none" >

        </p>
        <input type="submit" class="btn btn-info">
    </form>
{% endblock %}

{% block js %}
    <script>
    $("#myfile").change(function () {
        // 文件阅读器对象
        // 1 先生成一个文件阅读器对象
        let myFileReaderObj = new FileReader();
        // 2 获取用户上传的头像文件
        let fileObj = $(this)[0].files[0];
        // 3 将文件对象交给阅读器对象读取
        myFileReaderObj.readAsDataURL(fileObj)  // 异步操作  IO操作
        // 4 利用文件阅读器将文件展示到前端页面  修改src属性
        // 等待文件阅读器加载完毕之后再执行
        myFileReaderObj.onload = function(){
             $('#myimg').attr('src',myFileReaderObj.result)
        }
    })
    </script>
{% endblock %}
后端代码@login_required
def set_avatar(request):
    if request.method == 'POST':
        file_obj = request.FILES.get('avatar')
        # models.UserInfo.objects.filter(pk=request.user.pk).update(avatar=file_obj)  # 不会再自动加avatar前缀
        # 1.自己手动加前缀
        # 2.换一种更新方式
        user_obj = request.user
        user_obj.avatar = file_obj
        user_obj.save()
        return redirect('/home/')
    blog = request.user.blog
    username = request.user.username
    return render(request,'set_avatar.html',locals())

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-1002605-1-1.html 上篇帖子: BBS子评论如何是实现 下篇帖子: 深浅copy底层原理
累计签到:528 天
连续签到:1 天
 楼主| 发表于 2022-10-30 10:34:57 | 显示全部楼层
# bbs项目总结
在开发任意的web项目的时候 其实到了后期需要写的代码会越来越少
都是用已经写好的url填写到a标签href属性完成跳转即可

[主要功能总结]
    1、表设计 开发流程(粗糙流程。还可以细化)
    2、注册功能
        form组件使用
        头像动态展示
        错误信息提示
    3、登录功能
        图片验证码
        滑动验证码
    4、首页展示
        media配置
        主动暴露任意资源接口
    5、个人站点展示
        侧边栏展示
        侧边栏筛选
        侧边栏inclusion_tag制作
    6、文章详情页
        点赞点踩
        根评论、子评论
    7、后台管理
[针对bbs需要你掌握每一个功能的书写思路和内部逻辑,之后再去敲代码熟悉找感觉]

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表