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 %}
# 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 %}