Django - BBS - 项目学习 - 后台管理系统的实现(当前用户添加文章)

目录

一、路由设计

二、 视图函数

2-1 后台页面实现

2-2 文章添加操作(BeautifulSoup模块使用)

三、前端设计

3-1 母版设计

3-2 继承子版 - 文章的简单显示

3-3 继承子版 - 文章的添加(KindEditor插件的使用)


一、路由设计

from django.conf.urls import url
from django.contrib import admin
from bbs import views

from django.views.static import serve
from mybbs.settings import MEDIA_ROOT

urlpatterns = [
    url(r'^$', views.index),

    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    # 用于login前端页面对于验证码的获取
    url(r'^get_valid_code/', views.get_valid_code),

    url(r'^index/', views.index),
    url(r'^register/', views.register),
    url(r'^logout/', views.logout),
    url(r'^change_pwd/', views.change_pwd),
    url(r'^change_avatar/', views.change_avatar),

    url(r'^media/(?P<path>.*)', serve, {"document_root": MEDIA_ROOT}),

    # 点赞的路由
    url(r'^diggit/$', views.diggit),
    # 评论路由
    url(r'^commit_content/$', views.commit_content),
    # 后台管理页面
    url(r'^backend', views.backend),
    # 添加文章
    url(r'^add_article', views.add_article),
    # 富文本编辑器上传图片
    url(r'^upload_img', views.upload_img),

    # 三个过滤(分类,标签,归档) - 用于进入点击左边导航后的个人站点的文章显示
    # 分组分出三个(用户名,category|tag|archive中的一个,可能是分类id,tag_id,时间)
    url(r'^(?P<username>[\w]+)/(?P<condition>category|tag|archive)/(?P<param>.*)', views.user_blog),
    # 个人主页的文章查看路由
    url(r'^(?P<username>[\w]+)/article/(?P<id>\d+)', views.article_detail),

    # 上方未匹配到,接收参数匹配个人站点 有名分组
    url(r'^(?P<username>[\w]+)$', views.user_blog),

]

二、 视图函数

2-1 后台页面实现

from django.shortcuts import render, HttpResponse, redirect
from bbs import models

# --------------后台管理-----------------
@login_required(login_url='/login/')
def backend(request):
    '''
    后台管理
    :param request:
    :return:
    '''
    if request.method == 'GET':
        # 查询出当前登录用户的所有文章
        blog = request.user.blog
        article_list = models.Article.objects.filter(blog=blog)
        return render(request, 'back/backend.html', locals())

2-2 文章添加操作(BeautifulSoup模块使用)

 

from django.shortcuts import render, HttpResponse, redirect
from bs4 import BeautifulSoup
from bbs import models
import os
from mybbs import settings


# ---------------添加新文章------------------
@login_required(login_url='/login/')
def add_article(request):
    '''
    使用用模块:BeautifulSoup4(bs4)做爬虫,解析html页面获取文章内源码的所有文本信息
    - 导入 from bs4 import BeautifulSoup
    :param request:
    :return:
    '''
    if request.method == 'GET':
        return render(request, 'back/add_article.html', locals())

    elif request.method == 'POST':
        title = request.POST.get('title')
        content = request.POST.get('content')
        # 第一个参数:要解析的html内容,第二个参数:以什么解析器,解析我的页面
        # html.parser 是bs4 内置的解析器.也可以lxml,但是需要安装
        soup = BeautifulSoup(content, 'html.parser')
        print(soup)
        # soup=BeautifulSoup(content,'lxml')

        # 通过bs4模块,去掉script标签,处理xss攻击
        # 查询出所有html标签
        tags = soup.find_all()
        for tag in tags:
            if tag.name == 'script':
                # 过滤出是sctipt的标签,删除掉script的标签以及内容
                tag.decompose()
        # 取出html标签中所有文本内容 soup.text
        # soup.text[0:150] 截取文字的前150个,作为摘要
        desc = soup.text[0:150]
        # 注意soup内放置所有html标签加文本,如果使用soup.text仅仅存储文本,前端显示会无法显示需要格式
        ret = models.Article.objects.create(title=title, desc=desc, content=str(soup), blog=request.user.blog)
        return redirect('/backend/')


def upload_img(request):
    '''
    在文章内部实现图片的上传 -- 本质是文件的上传
    :param request:
    :return:
    '''
    # 获取文件
    myfile = request.FILES.get('myfile')
    # 处理存储图片的路径
    path = os.path.join(settings.BASE_DIR, 'media', 'img')
    # 不存在这个文件夹则创建
    if not os.path.isdir(path):
        os.mkdir(path)
    # 图片的路径,文件夹+图片名称
    file_path = os.path.join(path, myfile.name)
    with open(file_path, 'wb') as f:
        for line in myfile:
            f.write(line)

    # 按照要求来处理
    '''
            //成功时
        {
                "error" : 0,
                "url" : "http://www.example.com/path/to/file.ext"
        }
        //失败时
        {
                "error" : 1,
                "message" : "错误信息"
        }
    '''
    dic = {'error': 0, 'url': '/media/img/%s' % myfile.name}
    return JsonResponse(dic)

 

三、前端设计

3-1 母版设计

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    {#   bootstrap.js 是基于jquery的,所以要用它,必须先导入jquery .并且在它上面导入#}
    <script src="/static/jquery-3.3.1.js"></script>
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
    <title>后台管理</title>
    <style>
        .head {
            height: 60px;
            background: #6FA5DB;
            margin-bottom: 20px;
        }
    </style>
</head>
<body>
<div class="head">
    <h3>后台管理</h3>
</div>
<div class="container-fluid">
    <div class="row">

        <div class="col-md-3">
            <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
                <div class="panel panel-default">
                    <div class="panel-heading" role="tab" id="headingOne">
                        <h4 class="panel-title">
                            <a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne"
                               aria-expanded="true" aria-controls="collapseOne">
                                操作
                            </a>
                        </h4>
                    </div>
                    <div id="collapseOne" class="panel-collapse collapse in" role="tabpanel"
                         aria-labelledby="headingOne">
                        <div class="panel-body">
                            <a href="/add_article/">添加文章</a>
                        </div>
                    </div>
                    <div id="collapseOne" class="panel-collapse collapse in" role="tabpanel"
                         aria-labelledby="headingOne">
                        <div class="panel-body">
                            <a href="">添加随笔</a>
                        </div>
                    </div>
                    <div id="collapseOne" class="panel-collapse collapse in" role="tabpanel"
                         aria-labelledby="headingOne">
                        <div class="panel-body">
                            <a href="">其他操作</a>
                        </div>
                    </div>
                </div>
            </div>


        </div>
        <div class="col-md-9">
            <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 home %}
                        {% endblock %}



                    </div>
                    <div role="tabpanel" class="tab-pane" id="profile">随笔页面</div>
                    <div role="tabpanel" class="tab-pane" id="messages">日志页面</div>
                    <div role="tabpanel" class="tab-pane" id="settings">链接页面</div>
                </div>

            </div>
        </div>
    </div>

</div>
</div>
</body>
</html>

3-2 继承子版 - 文章的简单显示

{% extends 'back/back_base.html' %}

{% block home %}
    <table class="table table-hover table-striped">
        <thead>
        <tr>
            <th>文章标题</th>
            <th>发布时间</th>
            <th>评论数</th>
            <th>点赞数</th>
            <th>修改</th>
            <th>删除</th>
        </tr>
        </thead>
        <tbody>
        {% for article in article_list %}
            <tr>
                <td><a href="">{{ article.title }}</a></td>
                <td>{{ article.create_time|date:'Y-m-d H:i:s' }}</td>
                <td>{{ article.commit_num }}</td>
                <td>{{ article.up_num }}</td>
                <td><a href="">修改</a></td>
                <td><a href="">删除</a></td>
            </tr>

        {% endfor %}

        </tbody>

    </table>
{% endblock %}

 

3-3 继承子版 - 文章的添加(KindEditor插件的使用

{% extends 'back/back_base.html' %}

{% block home %}
    <div>
        <p>添加文章</p>
        <form action="/add_article/" method="post">
            {% csrf_token %}
            <p>标题</p>
            <p><input type="text" name="title" class="form-control"></p>
            <p>内容(KindEdit编辑器,不支持拖放/粘贴上传图片)</p>
            <p>
             <textarea name="content" id="editor_id" cols="30" rows="10"></textarea>
            </p>
            <input type="submit" class="btn btn-danger" value="提交">
        </form>
    </div>

    <script charset="utf-8" src="/static/kindeditor/kindeditor-all.js"></script>
    <script>
        KindEditor.ready(function (K) {
            window.editor = K.create('#editor_id', {
                width: '100%',
                height: '500px',
                //可以使用 item 控制要显示的控件,即上传图片、加粗等控件。默认为全部显示
                resizeType: 0,
                //上传图片,uploadJson 指的是上传的路径,在路由内进行配置
                uploadJson: '/upload_img/',
                //添加一些额外的参数,即传输过程中的添加属性
                extraFileUploadParams: {
                    'csrfmiddlewaretoken': '{{ csrf_token }}'
                },
                //修改默认上传文件的名字
                filePostName: 'myfile'

            })

        });
    </script>
{% endblock %}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值