首页 > 其他分享 >django_博客练习(文章详情/点赞/评论)

django_博客练习(文章详情/点赞/评论)

时间:2023-01-08 20:22:58浏览次数:45  
标签:obj text django pk num 详情 点赞 article id

文章详情页

渲染文章内容

侧边栏有分类显示

通过设置路由的方式 传递参数 文章id 作者用户名

文章是通过文章对象渲染到前端的,所以你点击文章时也可以告诉后端你点击的是哪一篇文章

路由设置

  path('<str:username>/p/<str:article_id>/', views.article),

后端代码

通过前端传递的参数 拿到作者对象 和文章对象

通过orm分组查询方法 拿到每个分类下文章数量 和 每个标签 每个时间段下的文章

def article(request, username, article_id):
    # 提交评论时的操作
    if request.method == 'POST':
        text = request.POST.get('text')
        article_id = request.POST.get('article_pk')
        name = request.POST.get('name')
        parent_id = request.POST.get('parent_id')
        print(parent_id)
        name_id = models.UserInfo.objects.filter(username=name).first().id
        models.Article.objects.filter(pk=article_id).update(comment_num=F('comment_num') + 1)
        models.Comment.objects.create(content=text, article_id=article_id, user_id=name_id, parent_id=parent_id)
        back_dict = {'msg': '评论成功'}
        return JsonResponse(back_dict)
      
    # 渲染文章详情页 

    user_obj = models.Site.objects.filter(name=username).first()
    
    category_list = models.Category.objects.filter(site=user_obj).annotate
    (article_num=Count("article__pk")).values( 'name', 'article_num', 'pk')
    # 拿到分类列表 根据外键关联站点 拿到站点下的所有分类 根据分类分组查询每个分类下的文章数量
    
    tag_list = models.Tag.objects.filter(site=user_obj).annotate
    (article_num=Count("article__pk")).values('name','article_num','pk')
    # 拿到所有标签  通过外键关联标签 然后根据标签进行分组 统计分组下所有的分组数量
    
    time_list = models.Article.objects.filter(site=user_obj).annotate
    (month=TruncMonth('create_time')).values('month').annotate(
    article_num=Count("pk")).values('month', 'article_num')
    # 拿到所有时间 针对文章时间进行分组 分组后 再次分组 通过月份分组 然后统计每个月份
    # 下的所有文章数量
    
    article_obj = models.Article.objects.filter(id=article_id).first()
    
    comment_list = models.Comment.objects.filter(article_id=article_obj)

    return render(request, 'articlePage.html', locals())

前端代码

网页继承了首页的顶部导航

接收后端传递的对象列表 统计侧边栏数据展示

{% extends 'homePage.html' %}

{% block title %}
    {{ user_obj.name }}
{% endblock %}

{% block css %}
 

{% endblock %}


# 文章侧边栏渲染
{% block content %}
    <div class="col-md-2">
        <div class="panel panel-default">
            <div class="panel-heading text-center">文章分类</div>
            <div class="panel-body text-center" style="height: 200px">
                {% for category in category_list %}
                    <p><a href="/{{ user_obj.name }}/category/{{ category.pk }}/"STYLE="color: #4cb3fa">{{ category.name }}({{ category.article_num }})</a></p>
               # 分类名称(文章数量)
                {% endfor %}
            </div>
        </div>
        <div class="panel panel-default">
            <div class="panel-heading text-center">文章标签</div>
            <div class="panel-body" style="height: 200px">
                <div class="panel-body text-center" style="height: 200px">
                    {% for tag in tag_list %}
                        <p><a href="/{{ user_obj.name }}/tag/{{ tag.pk }}/"                               STYLE="color: #4cb3fa">{{ tag.name }}({{ tag.article_num }})</a></p>
                  # 标签名称(文章数量)
                    {% endfor %}
                </div>
            </div>
        </div>
        <div class="panel panel-default">
            <div class="panel-heading text-center">日期归档</div>
            <div class="panel-body" style="height: 200px">
                <div class="panel-body text-center" style="height: 200px">
                    {% for time in time_list %}
                        <p><a href="/{{ user_obj.name }}/archive/{{ time.month|date:'Y-m' }}/"STYLE="color: #4cb3fa">{{ time.month|date:'Y-m' }}({{ time.article_num }})</a></p>
                  # 时间渲染 年月(文章数量)
                    {% endfor %}
                </div>
            </div>
        </div>
    </div>
    
    
    <div class="col-md-9">
        <div class="media">
            <h2 class="media-heading"
                style="margin-bottom: 14px;margin-left: 8px">{{ article_obj.title }}</h2>
             # 文章标题渲染
            <div class="media-body" style="padding-left: 10px">
                {{ article_obj.content|safe }}
            </div>
            # 文章内容渲染
            <div style="padding-top: 18px">
                <p>
                    <span style="font-size: 12px;color: #999999">&nbsp;&nbsp;{{ article_obj.create_time|date:'Y-m-d H:i' }}</span>
                    <span style="font-size: 12px;color: #999999">&nbsp;&nbsp;点赞:{{ article_obj.up_num }}</span>
                    <span style="font-size: 12px;color: #999999">&nbsp;&nbsp;反对:{{ article_obj.down_num }}</span>
                    <span style="font-size: 12px;color: #999999">&nbsp;&nbsp;评论:{{ article_obj.comment_num }}</span>
                </p>
            </div>
        </div>
        <hr>
        {# 展示文章已有评论 #}
        <p STYLE="margin-bottom: 30PX;font-size: 18px;color: #999999">文章评论:</p>
        {% if comment_list %}
            {% for comment_obj in comment_list %}
                <span style="color: #999999">#{{ forloop.counter }}楼&nbsp;&nbsp;<a
                        href="/{{ comment_obj.user.username }}/">{{ comment_obj.user.username }}</a>
            &nbsp;&nbsp;{{ comment_obj.create_time|date:'Y-m-d H:i' }} </span>
                {% if request.user.is_authenticated %}
                    <span><a href="#" style="margin-left: 40px" class="reply"
                             username="{{ comment_obj.user.username }}" parent_id="{{ comment_obj.pk }}">回复</a></span>
                {% endif %}
                <p style="margin-top: 10px;font-size: 14px;color: #616161">{{ comment_obj.content }}</p>
                <hr>
            {% endfor %}
        {% else %}
            <span style="color: #999999;margin-left: 8px;">该文章暂无评论</span>
        {% endif %}

        {% if request.user.is_authenticated %}
            {# 展示评论框 #}
            <div class="row">
                <div class="col-md-6">
                    <textarea class="form-control" rows="3" id="text" style="height: 140px;margin-top: 20px"
                              placeholder="请输入内容..."></textarea>
                    <button class="text-center" style="margin-top: 20px;" id="button">发布评论</button>
                    <span style="color: #fa7373" id="a001"></span>
                </div>
            </div>

        {% endif %}

    </div>

{% endblock %}


{% block script %}
    <script>
        let parent = null

        $('.reply').click(function () {
            let username = '@' + $(this).attr('username') + '\n';
            $('#text').val(username).focus();
            parent = $(this).attr('parent_id')
        })
        $('#button').click(function () {
            let text = $('#text').val()
            if (!text) {
                $('#a001').text('评论不可以为空')
            } else {
                $.ajax({
                    url: '',
                    type: 'post',
                    data: {
                        'text': text, 'article_pk': '{{ article_obj.pk }}', 'csrfmiddlewaretoken': '{{ csrf_token }}',
                        'name': '{{request.user.username}}','parent_id':parent
                    },
                    success: function (args) {
                        $('#a001').text(args.msg)
                        window.location.reload()

                    }
                })
                {# 发送ajax请求给存储评论的路由 #}
            }
            {# text就是评论的具体内容 #}
        })


        $('.upordown').click(function () {
            let isup = $(this).hasClass('diggit')
            if (isup) {
                $.ajax({
                    url: '/up_or_down/',
                    type: 'post',
                    data: {
                        'csrfmiddlewaretoken': '{{ csrf_token }}',
                        'article_pk': '{{ article_obj.pk }}',
                        'isup': isup
                    },
                    success: function (args) {
                        $('#span').text(args.msg)
                        if (args.code === 10000) {
                            let num = Number($('#upup_count').val()) + 1;
                            $('#upup_count').text(num)
                        } } }) } else {
                $.ajax({
                    url: '/up_or_down/',
                    type: 'post',
                    data: {
                        'csrfmiddlewaretoken': '{{ csrf_token }}',
                        'article_pk': '{{ article_obj.pk }}',
                        'isup': isup
                    },
                    success: function (args) {
                        $('#span').text(args.msg)
                        if (args.code === 10001) {
                            let num = Number($('#downdown_count').val()) + 1;
                            $('#downdown_count').text(num)
                        }}})}})
    </script>


{% endblock %}

点赞点踩功能

前端渲染 可直接复制别人css样式和html代码

   <style>
        #div_digg {
            float: contour;
            margin-left: 8px;
            margin-right: 30px;
            font-size: 12px;
            width: 125px;
            text-align: center;
            margin-top: 20px;
        }

        .diggit {
            float: left;
            width: 46px;
            height: 52px;
            background: url('/media/upup.gif') no-repeat;
            text-align: center;
            cursor: pointer;
            margin-top: 2px;
            padding-top: 5px;
        }

        .buryit {
            float: left;
            margin-left: 20px;
            width: 46px;
            height: 52px;
            background: url('/media/downdown.gif') no-repeat;
            text-align: center;
            cursor: pointer;
            margin-top: 2px;
            padding-top: 5px;
        }

        .clear {
            clear: both;
        }

        .diggword {
            margin-top: 5px;
            margin-left: 0;
            font-size: 12px;
            color: #808080;
        }

    </style>      
      
 
      
      {# 点赞样式开启 #}
        <div id="div_digg" class="text-center">
            <div class="diggit upordown" id="upup">
                <span class="diggnum" id="upup_count">{{ article_obj.up_num }}</span>
            </div>
            <div class="buryit upordown" id="downdown">
                <span class="burynum" id="downdown_count">{{ article_obj.down_num }}</span>
            </div>
            <div class="clear"></div>
            <div class="diggword" id="digg_tips">
            </div>
        </div>
        <div style="margin-top: 10px"><span id="span"
                                            style="color: #f58282;padding-top: 10px;font-size: 14px"></span></div>
        {# 点赞样式结束 #}
        
        
        
        
<script>  
        
         $('.upordown').click(function () {
         # 通过查询属性值绑定事件
            let isup = $(this).hasClass('diggit')
            # 通过区分calss属性值来判断是点赞还是点踩
            if (isup) {
                $.ajax({
                    url: '/up_or_down/',
                    # 针对这个功能 单独开一个路由
                    type: 'post',
                    data: {
                        'csrfmiddlewaretoken': '{{ csrf_token }}',
                        'article_pk': '{{ article_obj.pk }}',
                        'isup': isup
                        # 发送布尔值到后端 ture false代表踩
                    },
                    success: function (args) {
                        $('#span').text(args.msg)
                        if (args.code === 10000) {
                            let num = Number($('#upup_count').val()) + 1;
                            # 时时改变前端展示值 对标签数据进行加一
                            # 只是前端展示改变 没有做后端数据请求优化性能
                            $('#upup_count').text(num)
                        }}})} else {
                $.ajax({
                    url: '/up_or_down/',
                    type: 'post',
                    data: {
                        'csrfmiddlewaretoken': '{{ csrf_token }}',
                        'article_pk': '{{ article_obj.pk }}',
                        'isup': isup
                    },
                    success: function (args) {
                        $('#span').text(args.msg)
                        if (args.code === 10001) {
                            let num = Number($('#downdown_count').val()) + 1;
                            $('#downdown_count').text(num)
                        }}})}})
</script>

后端代码

指定一个空字典 用来返回给前端回应ajax请求

1.判断用户是否登录

2.判断文章是否是用户自己的

3.判断用户是否已经对该文件进行过操作

4.录入数据 对文章的点赞数普通字段自增一 这里用到了F方法

5.点赞点踩表创建数据 哪个用户对哪个文章进行了点赞还是点踩

@login_required(login_url='/login/')
def up_or_down_func(request):
    back_dict = {'msg': ''}
    if request.user.is_authenticated:
        if request.method == 'POST':
            article_id = request.POST.get('article_pk')
            isup = request.POST.get('isup')
            # 判断是否是自己的文章 自己不能给自己点赞
            if models.UserInfo.objects.filter(site__article__pk=article_id).first() == request.user:
                back_dict['msg'] = '不能给自己的文章操作'
            # 判断是否已经对这个文章进行过操作
            elif models.Up_and_Down.objects.filter(user_id=request.user.id).filter(article_id=article_id):
                back_dict['msg'] = '您已经评价过了'
            else:
                isup = json.loads(isup)
                if isup:
                    back_dict['msg'] = '点赞成功'
                    back_dict['code'] = 10000
                    models.Article.objects.filter(pk=article_id).update(up_num=F('up_num') + 1)
                else:
                    back_dict['msg'] = '反对成功'
                    back_dict['code'] = 10001
                    models.Article.objects.filter(pk=article_id).update(down_num=F('down_num') + 1)
                models.Up_and_Down.objects.create(user_id=request.user.id, article_id=article_id, is_up=isup)
        # 开始录入点赞数据
    else:
        back_dict['msg'] = '请先登录'
    return JsonResponse(back_dict)

标签:obj,text,django,pk,num,详情,点赞,article,id
From: https://www.cnblogs.com/moongodnnn/p/17035266.html

相关文章

  • Django views.py 增,删,改
    fromdjangoimportformsfromdjango.shortcutsimportrender,redirectfromapp01importmodels#Createyourviewshere.defdepart_list(request):  """......
  • python django 云招聘系统(课设、毕设、学习)
    pythondjango云招聘系统(课设、毕设、学习)pythondjango简历系统pythondjango招聘系统pythondjango职位招聘后端:pythondjango数据库:MySQL5.7前端:htmlcssjs等涉及......
  • 万邦虾皮shopee取ID商品详情数据 API 返回值说明,万邦推动企业信息化
    onebound.shopee.item_get公共参数请求地址: https://console.open.onebound.cn/console/?i=Anzexi名称类型必须描述keyString是调用key(必须以GET方式拼接在U......
  • django
    django1纯手撸web框架、wsgiref模块下的手撸框架、jinja2模版语法、django框架简介、下载、基本操作等2django静态文件相关配置、请求方法、链接mysql以及django的ORM......
  • Django里ORM常用关键字
    一、ORM常用关键字 #关键概览1.create()2.filter()3.first()last()4.update()5.delete()6.all()7.values()8.values_list()9.distinct()10.order_by()11.g......
  • Python 迭代器Iterator详情
    1.什么是迭代器?迭代器是一个表示数据流的对象,当我们调用next()方法时会返回容器中的下一个值迭代器中包含__iter__和__next__()方法。通过__iter__方法可以返回迭代器......
  • Django模板展示
    模板配置模板放在项目跟目录下,或者放在app下都可以,在settings.py文件配置模板路径'DIRS':[os.path.join(BASE_DIR,'templates')]登录模板登......
  • 亚马逊UL测试报告详情
    UL认证和UL测试报告有那些区别1、UL检测报告:是根据产品选用相应UL标准进行测试合格后,出具合格的测试报告。(UL测试报告是针对亚马逊的)2、UL认证:UL认证自愿申请的,是全球认可度......
  • 在命令行中创建Django项目
    1、cmd先进入你要放项目的目录。在命令行输入:django-adminstartproject项目名 。回车,此时创建了一个项目2、创建好了一个diango项目,然后再需要创建自己的一个应用项......
  • django-1.1环境安装
    环境安装1.创建虚拟环境mkvirtualenvdjango_py3_1.11-ppython3注意需要联网2.安装Django使用django1.11.11版本,注意需要联网pipinstalldjango==1.11.113.......