BBS 06

发布时间 2023-12-13 15:52:35作者: 拆尼斯、帕丁顿

事务

事务:四大特性
-原子性
-一致性
-持久性
-隔离性


# 点赞点踩案例
1 点赞点踩增加记录
2 文章表中数字+1


# django中使用事务
1 导入
from django.db import transaction
2 使用上下文管理器使用
with transaction.atomic():
写的代码,会要么都成功
要么都失败

评论render显示

https://www.cnblogs.com/lisixian/

#1 前端使用bootstrap的列表组

前端

  <div>
        <span id="id_commit_text">评论列表
        </span>
    </div>
    <ul class="list-group">
        {% for commit in commit_list %}
            <li class="list-group-item">

                <div>
                    <span><a href=""># {{ forloop.counter }} 楼</a></span>
                    <span>{{ commit.create_time|date:"Y-m-d H:i" }}</span>
                    <span><a href="/{{ commit.user.username }}">{{ commit.user.username }}</a></span>
                </div>
                <div style="padding: 10px">
                    {# 判断 parent_id是否为空,如果为空,就是下面,如果不为空,找到父评论人名 @#}
                    {% if commit.parent_id %}
                        <a href="/{{ commit.parent_id.user.username }}">@ {{ commit.parent_id.user.username }}</a>

                    {% endif %}
                    <br>
                    {{ commit.content }}
                </div>

            </li>

        {% endfor %}


    </ul>
    </div>

  

后端

def article_detail(request, username, article_id):
    article = Article.objects.filter(pk=article_id).first()
    commit_list=Commit.objects.filter(article_id=article.id)
    return render(request, 'article_detail.html', locals())

  

根评论提交和ajax的显示

 前端提交

$("#btn_commit").click(function () {
            // 谁给哪篇文章 评论了什么内容---》必须登录
            var content = $("#id_text").val()
            if (content) {
                $.ajax({
                    url: '/commit/',
                    method: 'post',
                    data: {
                        article_id: '{{ article.id }}',
                        content: content,
                        csrfmiddlewaretoken: '{{ csrf_token }}'

                    },
                    success: function (data) {
                        console.log(data)
                        if (data.code == 100) {
                            // 把 字符串标签,拼接在后面   es6 模板字符串语法--》类似于python的 'asdfas%sasdf%d'
                            var html_content = `
                            <li class="list-group-item">
                                <p><span class="fa fa-address-card-o">${data.username}:</span></p>
                                <p>${data.content}</p>
                            </ul>
                            `
                            $('.list-group').append(html_content)
                        }
                    }
                })
            } else {
                $('#alert_error').removeClass('hidden')
            }

        })

  

后端接口

def commit(request):
    user = request.user
    if user.is_authenticated:
        article_id = request.POST.get('article_id')
        content = request.POST.get('content')
        with transaction.atomic():
            commit = Commit.objects.create(user=user, article_id=article_id, content=content)
            # 评论数 +1
            Article.objects.filter(pk=article_id).update(commit_number=F('commit_number') + 1)
        return JsonResponse({'code': '100', 'msg': '评论成功', 'content': commit.content,'username':user.username})
    else:
        return JsonResponse({'code': '101', 'msg': '没有登录'})

子评论提交--ajax显示

 前端

## html中:
<div class="pull-right">
<span style="margin-left: 10px;margin-right: 10px" class="replay"
username="{{ commit.user.username }}" commit_id="{{ commit.id }}"><a>回复</a></span>
<span>删除</span>
</div>

## js中:给回复绑定事件
var parent_id=null
$('.replay').click(function () {
    var username = "@" + $(this).attr('username') + '\n'
    $("#id_text").val(username)

    parent_id = $(this).attr('commit_id')
})

## 评论提交
$("#btn_commit").click(function () {
    var content = $("#id_text").val()
    if (parent_id) {
        var i = content.indexOf('\n')  // 找到 \n在字符串中得位置  4
        content = content.substring(i + 1) // 把字符串截断,只要 \n往后额
        console.log(content);
    }

    if (content) {
        $.ajax({
            url: '/commit/',
            method: 'post',
            data: {
                parent_id: parent_id,
                article_id: '{{ article.id }}',
                content: content,
                csrfmiddlewaretoken: '{{ csrf_token }}'

            },
            success: function (data) {
                console.log(data)
                if (data.code == 100) {
                    $("#id_text").val('') // 清空输入框内容
                    var html_content = `
                    <li class="list-group-item">
                    <p><span class="fa fa-address-card-o">${data.username}:</span></p>
                    <p>${data.content}</p>
                    </ul>
                    `
                    $('.list-group').append(html_content)
                } else if (data.code == 103) {
                    $("#id_text").val('') // 清空输入框内容
                    var html_content = `
                    <li class="list-group-item">
                    <p><span class="fa fa-address-card-o">${data.username}:</span></p>
                    <p>@${data.parent_name}</p>
                    <p>${data.content}</p>
                    </ul>
                    `
                    $('.list-group').append(html_content)

                }
            }
        })
    } else {
        $('#alert_error').removeClass('hidden')
    }

})

  

后端

def commit(request):
    user = request.user
    if user.is_authenticated:
        article_id = request.POST.get('article_id')
        content = request.POST.get('content')
        parent_id = request.POST.get('parent_id')
        with transaction.atomic():
            commit = Commit.objects.create(user=user, article_id=article_id, content=content, parent_id_id=parent_id)
            # 评论数 +1
            Article.objects.filter(pk=article_id).update(commit_number=F('commit_number') + 1)
            if commit.parent_id:
                return JsonResponse({'code': '103', 'msg': '评论成功', 'content': commit.content, 'username': user.username,
                                     'parent_name': commit.parent_id.user.username})
            else:
                return JsonResponse(
                    {'code': '100', 'msg': '评论成功', 'content': commit.content, 'username': user.username})
    else:
        return JsonResponse({'code': '101', 'msg': '没有登录'})

 

后台管理页面

 后端

 

@login_required(login_url='/login/')
def backend(request):
    article_list = Article.objects.filter(blog=request.user.blog)
    return render(request, 'backend/backend_index.html', locals())

前端backend_base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>后台管理</title>
    <script src="/static/js/jquery.min.js"></script>
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
    <script src="/static/bootstrap/js/bootstrap.min.js"></script>

</head>
<body>
<nav class="navbar navbar-default">
    <div class="container-fluid navbar-inverse">
        <div class="navbar-header ">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/">后台管理</a>
        </div>
    </div><!-- /.container-fluid -->
</nav>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-2">
            <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">
                            <ul class="nav nav-pills nav-stacked nav-pills-stacked-example">
                                <li role="presentation"><a href="#">新建文章</a></li>
                                <hr>
                                <li role="presentation"><a href="#">修改头像</a></li>
                                <hr>
                                <li role="presentation"><a href="#">草稿箱</a></li>
                            </ul>
                        </div>
                    </div>
                </div>
                <div class="panel panel-default">
                    <div class="panel-heading" role="tab" id="headingTwo">
                        <h4 class="panel-title">
                            <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion"
                               href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
                                分类
                            </a>
                        </h4>
                    </div>
                    <div id="collapseTwo" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTwo">
                        <div class="panel-body">
                            <ul class="nav nav-pills nav-stacked nav-pills-stacked-example">
                                <li role="presentation"><a href="#">分类一</a></li>
                                <hr>
                                <li role="presentation"><a href="#">分类二</a></li>

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

        </div>
        <div class="col-md-9">
            <div class="bs-example bs-example-tabs" data-example-id="togglable-tabs">
                <ul id="myTabs" class="nav nav-tabs" role="tablist">
                    <li role="presentation" class="active"><a href="#home" id="home-tab" role="tab" data-toggle="tab"
                                                              aria-controls="home" aria-expanded="true">文章</a></li>
                    <li role="presentation" class=""><a href="#profile" role="tab" id="profile-tab" data-toggle="tab"
                                                        aria-controls="profile" aria-expanded="false">随笔</a></li>
                    <li role="presentation" class="dropdown">
                        <a href="#" id="myTabDrop1" class="dropdown-toggle" data-toggle="dropdown"
                           aria-controls="myTabDrop1-contents" aria-expanded="false">更多 <span
                                class="caret"></span></a>
                        <ul class="dropdown-menu" aria-labelledby="myTabDrop1" id="myTabDrop1-contents">
                            <li><a href="#dropdown1" role="tab" id="dropdown1-tab" data-toggle="tab"
                                   aria-controls="dropdown1">相册</a></li>
                            <li><a href="#dropdown2" role="tab" id="dropdown2-tab" data-toggle="tab"
                                   aria-controls="dropdown2">测试</a></li>
                        </ul>
                    </li>
                </ul>
                <div id="myTabContent" class="tab-content">
                    <div role="tabpanel" class="tab-pane fade active in" id="home" aria-labelledby="home-tab">
                        {% block articles %}
                        
                        {% endblock %}
                    </div>
                    <div role="tabpanel" class="tab-pane fade" id="profile" aria-labelledby="profile-tab">
                        随笔
                    </div>
                    <div role="tabpanel" class="tab-pane fade" id="dropdown1" aria-labelledby="dropdown1-tab">
                        相册
                    </div>
                    <div role="tabpanel" class="tab-pane fade" id="dropdown2" aria-labelledby="dropdown2-tab">
                        更多
                    </div>
                </div>
            </div>


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


</body>
{% block script %}

{% endblock %}
</html>

  

backend_index.html

 

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

{% block articles %}

    <div>
        <table class="table table-striped">
            <thead>
            <tr>
                <th>文章id</th>
                <th>文章名字</th>
                <th>创建时间</th>
                <th>操作</th>
            </tr>
            </thead>
            <tbody>
            {% for article in article_list %}
                <tr>
                    <th scope="row">{{ article.id }}</th>
                    <td><a href="/{{ request.user.username }}/articles/{{ article.id }}.html">{{ article.title }}</a>
                    </td>
                    <td>{{ article.create_time|date:"Y年m月d日" }}</td>
                    <td><a href="">编辑</a> | <a href="/delete/{{ article.id }}">删除</a></td>
                </tr>
            {% endfor %}


            </tbody>
        </table>
    </div>

{% endblock %}

删除文章功能

<a href="/delete/{{ article.id }}">删除</a>



@login_required(login_url='/login/')
def delete_article(request, pk):
    Article.objects.filter(pk=pk).delete()
    return redirect('/backend/')

  

新增文章功能

 后台

@login_required(login_url='/login/')
def add_article(request):
    if request.method == 'GET':
        # 当前作者所有分类
        category_list = Category.objects.filter(blog=request.user.blog).all()
        tag_list = Tag.objects.filter(blog=request.user.blog).all()
        return render(request, 'backend/add_article.html', locals())
    else:
        title = request.POST.get('title')
        content = request.POST.get('content')
        category = request.POST.get('category')
        desc = content[0:70]
        tag = request.POST.getlist('tag')
        article = Article.objects.create(title=title, desc=desc, content=content, category_id=category,
                                         blog=request.user.blog)
        # 中间表如果自动生成,有如下方式操作中间表
        article.tag.add(*tag)  # id 或对象 都可以   article.tag.add(1,2)
        # article.tag.clear()
        # article.tag.set()
        # article.tag.remove()

        return redirect('/backend/')

前台

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

{% block articles %}

    <div>
        <h3 class="text-center">添加文章</h3>
        <form method="post">
            {% csrf_token %}
            <div class="form-group">
                <label for="">标题</label>
                <input type="text" class="form-control" name="title">
            </div>
            <div class="form-group">
                <label for="">内容</label>
                <textarea name="content" id="" cols="200" rows="10" class="form-control"></textarea>
            </div>
            <div class="form-group">
                <label for="">分类</label>
                <select class="form-control" name="category">
                    {% for category in category_list %}
                        <option value="{{ category.id }}">{{ category.name }}</option>
                    {% endfor %}


                </select>

            </div>
            <div class="form-group">
                <label for="">标签</label>
                <select class="form-control" multiple name="tag">
                    {% for tag in tag_list %}
                        <option value="{{ tag.id }}">{{ tag.name }}</option>
                    {% endfor %}


                </select>

            </div>

            <div class="text-center">
                <button class="btn btn-danger">新增文章</button>
            </div>
        </form>

    </div>
{% endblock %}