一、昨日内容回顾
-模板语法的for循环
-bootstrap的媒体组
-显示头像: articel.blog.userinfo 有可能没有 :在admin中建立关系
-注册---》申请开启博客功能
-图标库
-font-awesome-4.7.0
-头部导航栏
-左侧筛选:3个面板
-右侧文章列表:首页文章列表差不多
-使用了模板继承---》base.html----》尽量多的写block
-查询出标签id,名字,标签下的文章数
-查询出分类id,名字,分类下的文章数
-查询出时间名字,时间下的文章数
-查分类id,名字,当前博客下的----》单表查询+过滤
-查分类id,名字,当前博客下的,分类下的文章数---》分组 group by
selcet category.id,category.name,count(article.id) as c from category,article where category.id=article.cagegory and category.blog=2 group by category.id; Category.object.filter(blog=user.blog).values('id').annotate(c=Count(articel__id)).values('id','name','c')
-设计路由
-按标签过滤:/lqz/tag/标签id号.html
-按分类过滤:/lqz/category/分类id号.html
-按时间过滤:/lqz/archive/202209.html
-三个路由归一
re_path('^(?P<name>\w+)/(?P<type_name>tag|category|archive)/(?P<condition>\d+).html', views.site),
-视图函数,统一用site视图函数
-
-当页面加载完成发送ajax请求
$(function () {
$.ajax({
url:'/get_banner/',
type:'get',
success:function (data){
console.log(data)
// {code:100,msg:成功,data:[{id:1,img:/banner/bannner1.jpg,name:'asdf',link:'/login/'},{id:1,img:/banner/bannner1.jpg,name:'asdf',link:'/login/'}]}
// 通过dom操作,把img地址,放到 轮播图img的src中即可
}
})
})
def get_banner(request):
res = Banner.objects.all().values('id', 'img', 'name')[:2]
return JsonResponse({'code': 100, 'msg': '成功', 'data': res})
"""
$(function ()就是文件加载完成的意思
windows.onload也行
"""
二、模板和模板语法的区别
-django中:模板语法,dtl:django template language,django自己设计,写的
-flask中:模板语法:jinja2,第三方
-java: jsp 理解为:java web 的模板语言
-php: php <? php语言 >
-xx.html 中写了python代码,这个不是前端页面,叫模板
"""
个人的理解是前端就是用前端自己的语言写的。模板的渲染是后端完成的,所以前端中的python语言理论上为模板
"""
views.py中
def test(request):
return render(request, 'test.html',
context={'name': "lqz", 'age': 19, 'a': 'a', 'l': [1, 2, 3], 'd': {'name': 'lyf', 'age': 40}})
——————————————————————————————————————————————————
test.html中
<script>
// 可以在js代码用模板渲染,但是只能用数字,字符串(加引号),列表 不能用元组,字典,对象 test
// 后端模板中得name给js的name
var name ='{{name}}'
// 后端模板中得age给js的age
var age = {{ age }}
var l= {{ test }}
//var d={'name': 'lyf', 'age': 40}
console.log(age)
console.log(name)
console.log(l)
//console.log(d)
$('h2').html(age)
// 把js的变量l,给python的视图函数中得l
</script>
"""
1.对于结果是数字的,就没有问题
2.对于结果是字符串的
var name ={{name}} 本质上是
var name = lqz 所以会报错
var name ='{{name}}' 就得自己加上引号
3.不能用元组,字典,对象 test
"""
三、左侧使用inclusion_tag方案实现(第58天也有)
首先是inclusion_tag的作用,是可以让一部分的网页作为可以用模型渲染的函数调用
-第一步:在app中创建包:templatetags
-第二步:在包下新建py文件:如:my_tags.py
-第三步:在py文件中导入
from django import template
第四步:实例化得到对象
register = template.Library()
第五步:使用register装饰函数
@register.inclusion_tag('left.html', name='left')
def left(name):
return {}
-第六步:在想引入inclusion_tag使用---》base.html 的栅格左侧占2个栅格的位置
{% load my_tags %}
{% left name%}
may_tag文件中
from django import template
from blog import models
from django.db.models.functions import TruncMonth, TruncDay, TruncYear, TruncHour
from django.db.models import Avg, Max, Min, Count
register = template.Library()
@register.inclusion_tag('left.html', name='left')
def left(name):
user = models.UserInfo.objects.filter(username=name).first()
tag_res = models.Tag.objects.filter(blog=user.blog).values('id').annotate(c=Count('article__id')).values_list('id', 'name', 'c')
category_res = models.Category.objects.filter(blog=user.blog).values('id').annotate(c=Count('article__id')).values_list('id', 'name', 'c')
data_res = models.Article.objects.filter(blog=user.blog).annotate(year_month=TruncMonth('create_time')).values('year_month').annotate(c=Count('id')).values_list('year_month', 'c')
print(tag_res)
print(category_res)
print(data_res)
return {'tag_res': tag_res, 'category_res': category_res, 'data_res': data_res,'user': user}
left 文件中(部分)
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">我的标签</h3>
</div>
<div class="panel-body">
<div>
{% for tag in tag_res %}
<div>
<a href="/{{ user.username }}/tag/{{ tag.0 }}.html">
<sapn>{{ tag.1 }}</sapn>
<span>{{ tag.2 }}</span>
</a>
</div>
{% endfor %}
</div>
</div>
</div>
具体使用在了base.html中
<div class="container-fluid">
<div class="row">
<div class="col-md-2">
{% load my_tag %}
{% left name %}
</div>
<div class="col-md-10">
{% block article %}
{% endblock %}
</div>
</div>
</div>
"""
总结:
1.templatetags文件名千万别写错
2.'left.html'表示拿来作为模块的文件,name='left'可以不写,默认就是下面的函数名
@register.inclusion_tag('left.html', name='left')
def left(name):
return {} # 字典的数据可以在left.html中使用
3缺啥参数就传啥参数,name比较特殊因为在渲染base的时候name就已经被site获取到了,就可以利用
{% left name %}传输给left
"""
四、文章详情页
name比较复杂
首先name在第一次被传入是在site中
之后点击用户的名字就等同于访问了site,并将name传给了site
views的site函数中,name被传入了参数,又用locals还给了site网页,所以site.html可以直接使用{{name}}
点击<a href="/{{ name }}/articles/{{ article.id }}.html">访问了article_detail
之后就接收了name
五、点赞点踩样式
<script>
// 点赞点踩写成1个事件
$(".up").click(function () {
var up = $(this).hasClass('diggit') // 判断点击的这个标签有没有diggit类,如果有就是true,up是true表示点赞,否则表示点踩
$.ajax({
url: '/up_and_down/',
type: 'post',
data: {
// 谁给那篇文章点赞或点踩---》谁可以不传,当前登录用户就是点赞人
//article_id:$('h2').attr('name') // 方式1:把文章id,放在某个标签中,使用jq取到id
article_id: '{{ article_detail.id }}',
up_or_down: up,
csrfmiddlewaretoken: '{{ csrf_token }}'
},
success: function (data) {
$('#digg_tips').html(data.msg)
if(data.code==100){
//
}
}
})
})
</script>
——————————————————————————————————————————————————————————————————
import json
from django.db.models import F
from django.db import transaction
def up_and_down(request):
res = {'code': 100, 'msg': '点赞成功'}
if request.user.is_authenticated:
article_id = request.POST.get('article_id')
up = json.loads(request.POST.get('up_or_down'))
count = UpAndDown.objects.filter(user=request.user, article_id=article_id).count()
if count:
res['code'] = 101
res['msg'] = '您已经点过了'
return JsonResponse(res)
else:
with transaction.atomic():
UpAndDown.objects.create(user=request.user, article_id=article_id, is_up=up)
if up:
Article.objects.filter(pk=article_id).update(up_num=F('up_num')+1)
res['msg'] = '点赞成功'
else:
Article.objects.filter(pk=article_id).update(down_num=F('down_num') + 1)
res['msg'] = '点踩成功'
return JsonResponse(res)
else:
res['code'] = 102
res['msg'] = '您没有登录,请先 <a href="/login/">登录</a>'
return JsonResponse(res)
——————————————————————————————————————————————————————————————————
"""
这里的第一个重点是 if request.user.is_authenticated: # 只要登录了就是当前登录用户,如果没登录就是匿名用户
这里的第二个重点是 with transaction.atomic(): #开启事务,保证,插入点赞点踩表和文章表增加1 ,要么都成功,要么都失败!!!!!!!!!
"""