BS -5

发布时间 2023-12-12 14:51:33作者: 拆尼斯、帕丁顿

侧边栏筛选

 后端

def category(request, username, category_id):
    user = UserInfo.objects.filter(username=username).first()
    if user:
        category_name = Category.objects.filter(pk=category_id).first().name
        article_list = Article.objects.filter(blog_id=user.blog.id).all().filter(category_id=category_id)
        res_category = Article.objects.filter(blog=user.blog).values('category_id').annotate(
            article_count=Count('id')).values(
            'category__id', 'category__name', 'article_count')
        res_tag = Article.objects.filter(blog=user.blog).values('tag__id').annotate(article_count=Count('id')).values(
            'tag__id', 'tag__name', 'article_count')
        res_date = Article.objects.filter(blog=user.blog).annotate(create_date=TruncMonth('create_time')).values(
            'create_date').annotate(article_count=Count('id')).values('create_date', 'article_count')

        return render(request, 'site.html', locals())
    else:
        return render(request, '404.html')


def tag(request, username, tag_id):
    user = UserInfo.objects.filter(username=username).first()
    if user:
        tag_name = Tag.objects.filter(pk=tag_id).first().name
        article_list = Article.objects.filter(blog_id=user.blog.id).all().filter(tag__id=tag_id)
        res_category = Article.objects.filter(blog=user.blog).values('category_id').annotate(
            article_count=Count('id')).values(
            'category__id', 'category__name', 'article_count')
        res_tag = Article.objects.filter(blog=user.blog).values('tag__id').annotate(article_count=Count('id')).values(
            'tag__id', 'tag__name', 'article_count')
        res_date = Article.objects.filter(blog=user.blog).annotate(create_date=TruncMonth('create_time')).values(
            'create_date').annotate(article_count=Count('id')).values('create_date', 'article_count')

        return render(request, 'site.html', locals())
    else:
        return render(request, '404.html')


def date_articel(request, username, date_y_m):
    user = UserInfo.objects.filter(username=username).first()
    if user:
        # 2023-11
        year, month = date_y_m.split('-')
        article_list = Article.objects.filter(blog_id=user.blog.id).all().filter(create_time__year=year,
                                                                                 create_time__month=month)
        res_category = Article.objects.filter(blog=user.blog).values('category_id').annotate(
            article_count=Count('id')).values(
            'category__id', 'category__name', 'article_count')
        res_tag = Article.objects.filter(blog=user.blog).values('tag__id').annotate(article_count=Count('id')).values(
            'tag__id', 'tag__name', 'article_count')
        res_date = Article.objects.filter(blog=user.blog).annotate(create_date=TruncMonth('create_time')).values(
            'create_date').annotate(article_count=Count('id')).values('create_date', 'article_count')

        return render(request, 'site.html', locals())
    else:
        return render(request, '404.html')

路由

path('<str:username>/category/<int:category_id>.html', views.category),
path('<str:username>/tag/<int:tag_id>.html', views.tag),
# 2023-11
path('<str:username>/archive/<str:date_y_m>.html', views.date_articel),

  

前端

{% block left %}
    <div class="panel panel-primary">
        <div class="panel-heading"><h3 class="panel-title">我的标签</h3></div>
        <div class="panel-body">
            {% for tag in res_tag %}
                <p><a href="/{{ user.username }}/tag/{{ tag.tag__id }}.html">{{ tag.tag__name }}({{ tag.article_count }})</a>
                </p>
                {% if not forloop.last %}

                    <hr>
                {% endif %}

            {% endfor %}


        </div>
    </div>
    <div class="panel panel-info">
        <div class="panel-heading"><h3 class="panel-title">随笔分类</h3></div>
        <div class="panel-body">

            {% for category in res_category %}
                <p>
                    <a href="/{{ user.username }}/category/{{ category.category__id }}.html">{{ category.category__name }}({{ category.article_count }})</a>
                </p>
                {% if not forloop.last %}

                    <hr>
                {% endif %}

            {% endfor %}


        </div>
    </div>
    <div class="panel panel-danger">
        <div class="panel-heading"><h3 class="panel-title">随笔档案</h3></div>
        <div class="panel-body">
            {% for item in res_date %}
                <p>
                    <a href="/{{ user.username }}/archive/{{ item.create_date|date:'Y-m' }}.html">{{ item.create_date|date:'Y年m月' }}({{ item.article_count }})</a>
                </p>
                {% if not forloop.last %}

                    <hr>
                {% endif %}

            {% endfor %}</div>
    </div>
{% endblock %}

  

侧边栏抽取

1.1 三个路由合三为一

# 3个路由合为一个
# path('<str:username>/category/<int:category_id>.html', views.site),
# path('<str:username>/tag/<int:tag_id>.html', views.site),
# path('<str:username>/archive/<str:date_y_m>.html', views.site),


# 为一个
#/lqz/archive/2023-11.html  --->username=lqz   choice=archive  condition=2023-11
# /lqz/tag/1.html--------> username=lqz  choice=tag    condition=1
#/lqz/category/3.html----> username=lqz  choice=category    condition=3
re_path('(?P<username>\w+)/(?P<choice>category|tag|archive)/(?P<condition>.*?).html', views.site),

# 个人站点路由放最后---》上面所有都匹配完了--->再看是不是个人站点
path('<str:username>', views.site),

  

四个视图函数合四为一

def site(request, username, **kwargs):  # 以上三种都能接收
    user = UserInfo.objects.filter(username=username).first()
    if user:
        article_list = Article.objects.filter(blog_id=user.blog.id).all()
        choice = kwargs.get('choice', None)
        condition = kwargs.get('condition', None)  # 如果 choice 有值,condition一定有
        if choice and choice == 'category':  # choice有值 说明不是个人站点的:可能是 tag筛选,标签筛选,日期筛选,并且choice是 category,按标签过滤的
            category_name = Category.objects.filter(pk=condition).first().name
            article_list = article_list.filter(category_id=condition)
        elif choice and choice == 'tag':
            tag_name = Tag.objects.filter(pk=condition).first().name
            article_list = article_list.filter(tag__id=condition)
        elif choice and choice == 'archive':
            date_y_m=condition
            year, month = condition.split('-')
            article_list = article_list.filter(create_time__year=year, create_time__month=month)
        res_category = Article.objects.filter(blog=user.blog).values('category_id').annotate(
            article_count=Count('id')).values('category__id', 'category__name', 'article_count')
        res_tag = Article.objects.filter(blog=user.blog).values('tag__id').annotate(article_count=Count('id')).values(
            'tag__id', 'tag__name', 'article_count')
        res_date = Article.objects.filter(blog=user.blog).annotate(create_date=TruncMonth('create_time')).values(
            'create_date').annotate(article_count=Count('id')).values('create_date', 'article_count')

        return render(request, 'site.html', locals())
    else:
        return render(request, '404.html')

  

侧边栏抽取

之前学过 include---》固定的,不能动态变化
# inclusion_tag---》返回一个动态的html片段---》编写方式类似于标签和过滤器
# 编写步骤
	1、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.
	2、在app中创建templatetags模块(模块名只能是templatetags)
	3、创建任意 .py 文件,如:my_tags.py
    4、导入,实例化得到对象 register的名字是固定的,不可改变
        from django import template
        register = template.Library()
                            
    5、使用装饰器
@register.inclusion_tag('left.html', name='left')
def left(username):
    user = UserInfo.objects.filter(username=username).first()
    res_category = Article.objects.filter(blog=user.blog).values('category_id').annotate(
        article_count=Count('id')).values('category__id', 'category__name', 'article_count')
    res_tag = Article.objects.filter(blog=user.blog).values('tag__id').annotate(article_count=Count('id')).values(
        'tag__id', 'tag__name', 'article_count')
    res_date = Article.objects.filter(blog=user.blog).annotate(create_date=TruncMonth('create_time')).values(
        'create_date').annotate(article_count=Count('id')).values('create_date', 'article_count')

    return {'user': user, 'res_category': res_category, 'res_tag': res_tag, 'res_date': res_date}
                            
  6、html片段
   <div>
    <div class="panel panel-primary">
        <div class="panel-heading"><h3 class="panel-title">我的标签</h3></div>
        <div class="panel-body">
            {% for tag in res_tag %}
                <p><a href="/{{ user.username }}/tag/{{ tag.tag__id }}.html">{{ tag.tag__name }}({{ tag.article_count }})</a>
                </p>
                {% if not forloop.last %}

                    <hr>
                {% endif %}

            {% endfor %}


        </div>
    </div>
    <div class="panel panel-info">
        <div class="panel-heading"><h3 class="panel-title">随笔分类</h3></div>
        <div class="panel-body">

            {% for category in res_category %}
                <p>
                    <a href="/{{ user.username }}/category/{{ category.category__id }}.html">{{ category.category__name }}({{ category.article_count }})</a>
                </p>
                {% if not forloop.last %}

                    <hr>
                {% endif %}

            {% endfor %}


        </div>
    </div>
    <div class="panel panel-danger">
        <div class="panel-heading"><h3 class="panel-title">随笔档案</h3></div>
        <div class="panel-body">
            {% for item in res_date %}
                <p>
                    <a href="/{{ user.username }}/archive/{{ item.create_date|date:'Y-m' }}.html">{{ item.create_date|date:'Y年m月' }}({{ item.article_count }})</a>
                </p>
                {% if not forloop.last %}

                    <hr>
                {% endif %}

            {% endfor %}</div>
    </div>


</div>                
  7、在模板中使用
     {% load common_left %}
    {% left username%}

  

文章页面

 后台

def article_detai(request, username, article_id):
    article = Article.objects.filter(pk=article_id).first()

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

  

前台

{% extends 'base.html' %}

{% block title %}
    {{ article.title }}
{% endblock %}

{% block site_name %}
    {{ article.blog.site_name }}
{% endblock %}

{% block content %}
    <h2 class="text-center">{{ article.title }}</h2>
    <hr>
    {{ article.content|safe }}
{% endblock %}

文章点赞

 后端

import json


# 加装饰器,只能实现,进不到这个函数中执行,无法定制返回给ajax的数据---》前端不好操作
def upanddown(request):
    # 当前登录用户,如果取不出来,需要返回让它登录
    user = request.user
    if user.is_authenticated:
        # 判断是点赞还是点踩
        article_id = request.POST.get('article_id')
        up_or_down = request.POST.get('up')  # 是字符串类型,转成 布尔
        up_or_down = json.loads(up_or_down)
        res = UpAndDown.objects.filter(article_id=article_id, user=user).first()
        if res:
            return JsonResponse({'code': 102, 'msg': '您已经点过了'})
        else:
            ######## 在一个视图函数中,操作了两个表---》这两个操作属于:同一个事务#####
            # 存点赞点踩表
            UpAndDown.objects.create(user=user, article_id=article_id, is_up=up_or_down)
            # 让文章的点赞或点踩加1
            if up_or_down:
                Article.objects.filter(pk=article_id).update(up_number=F('up_number') + 1)
                return JsonResponse({'code': 100, 'msg': '点赞成功'})
            else:
                Article.objects.filter(pk=article_id).update(down_number=F('down_number') + 1)
                return JsonResponse({'code': 100, 'msg': '点踩成功'})


    else:
        return JsonResponse({'code': 101, 'msg': '您没有登录,请先 <a href="/login/" style="color: red">登录</a>'})

  

前端

{% extends 'base.html' %}

{% block title %}
    {{ article.title }}
{% endblock %}

{% block header %}
    <link rel="stylesheet" href="/static/css/common_css.css">
{% endblock %}

{% block site_name %}
    {{ article.blog.site_name }}
{% endblock %}

{% block content %}
    <h2 class="text-center" article_id="{{ article.id }}">{{ article.title }}</h2>
    <hr>
    {{ article.content|safe }}
    <hr>
    <div id="div_digg">
        <div class="diggit digg">
            <span class="diggnum" id="digg_count">{{ article.up_number }}</span>
        </div>
        <div class="buryit digg">
            <span class="burynum" id="bury_count">{{ article.down_number }}</span>
        </div>
        <div class="clear"></div>
        <div class="diggword" id="digg_tips">

        </div>
    </div>
{% endblock %}



{% block script %}
    <script>
        // 笨办法,给点赞绑定一个事件,给点踩绑定一个事件---》分别提交
        $('.digg').click(function () {
            // 判断,如果点的div 有diggit类就是点赞
            var up = $(this).hasClass('diggit')
            console.log($('h2').attr('article_id'))
            let _this = this
            //发送ajax请求
            $.ajax({
                url: '/upanddown/',
                method: 'post',
                data: {  //谁(当前登录用户)对那篇文章(文章id)点赞或点踩(up)
                    article_id: '{{ article.id }}',
                    //article_id: $('h2').attr('article_id'),
                    up: up,
                    csrfmiddlewaretoken: '{{ csrf_token }}'
                },
                success: function (data) {
                    console.log(data)
                    $('#digg_tips').html(data.msg)
                    if (data.code == 100) {
                        // 让数字加1  赞+1  踩 +1
                        var num = Number($(_this).children('span').html())
                        $(_this).children('span').html(num + 1)

                    }
                }
            })
        })

    </script>
{% endblock %}