1. 程式人生 > 實用技巧 >django框架前後端混合專案之側邊欄及點贊點踩功能等相關內容-80

django框架前後端混合專案之側邊欄及點贊點踩功能等相關內容-80

1 側邊欄展示

#查詢當前站點下所有分類下的文章數
# python是解釋型語言,做垃圾回收
# python的cpython直譯器存在,jpython ,pypy

### 三個分組查詢
res_category =models.Category.objects.filter(blog=user.blog).annotate(num=Count('article__id')).values_list('name', 'num', 'id')
res_tag =models.Tag.objects.filter(blog=user.blog).annotate(num=Count('article__id')).values_list('name','num', 'id')
res_month =models.Article.objects.filter(blog=user.blog).annotate(month=TruncMonth('create_time')).values(
'month').annotate(c=Count('id')).order_by('-month').values_list('month', 'c')


### 根據年月分組的分析過程
id create_time month
1 2020-09-29 11:59:01.326770 2020-09 2
2 2020-09-29 11:59:37.299591 2020-09


3 2020-10-29 09:59:53.029608 2020-10 4
4 2020-10-29 12:00:11.200812 2020-10
5 2020-10-29 12:00:26.995485 2020-10
10 2020-10-30 09:45:14.887788 2020-10

8 2020-08-01 09:03:16.000000 2020-08 2
9 2020-08-01 09:24:24.000000 2020-08


models.Article.objects.filter(blog=user.blog).annotate(month=TruncMonth('create_time'))
.values('month').annotate(c=Count('id')).values_list('month', 'c')

頁面樣式

<div>
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">我的標籤</h3>
</div>
<div class="panel-body">
{% for tag in res_tag %}
<p><a href="/{{ name }}/tag/{{ tag.2 }}.html">{{ tag.0 }}({{ tag.1 }})</a></p>
{% 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="/{{ name }}/category/{{ category.2 }}.html">{{ category.0 }}({{ category.1 }})</a></p>
{% endfor %}


</div>
</div>
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">隨筆檔案</h3>
</div>
<div class="panel-body">
{% for month in res_month %}
<p>
<a href="/{{ name }}/archive/{{ month.0|date:'Y/m' }}.html">{{ month.0|date:'Y年m月' }}({{ month.1 }})</a>
</p>
{% endfor %}
</div>
</div>
</div>

2 側邊欄篩選

路由

re_path('^(?P<name>\w+)/(?P<query>category|tag|archive)/(?P<condition>.*).html$', views.site),

頁面

<div>
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">我的標籤</h3>
</div>
<div class="panel-body">
{% for tag in res_tag %}
<p><a href="/{{ name }}/tag/{{ tag.2 }}.html">{{ tag.0 }}({{ tag.1 }})</a></p>
{% 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="/{{ name }}/category/{{ category.2 }}.html">{{ category.0 }}({{ category.1 }})</a></p>
{% endfor %}


</div>
</div>
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">隨筆檔案</h3>
</div>
<div class="panel-body">
{% for month in res_month %}
<p>
<a href="/{{ name }}/archive/{{ month.0|date:'Y/m' }}.html">{{ month.0|date:'Y年m月' }}({{ month.1 }})</a>
</p>
{% endfor %}
</div>
</div>
</div>

檢視

def site(request, name, **kwargs):
# 分三種情況(根據標籤過濾,根據分類過濾,根據時間過濾)
user = models.UserInfo.objects.filter(username=name).first()
if user:
article_list = user.blog.article_set.all()
# 根據不同情況對article_list進行過濾,article_list是queryset物件,可以繼續filter
query = kwargs.get('query', None)
if query == 'category': # 說明走的是過濾的路由
condition = kwargs.get('condition')
article_list = article_list.filter(category_id=condition)
elif query == 'tag':
condition = kwargs.get('condition')
article_list = article_list.filter(tag__id=condition)
elif query == 'archive':
year, month = kwargs.get('condition').split('/') # 2020/09
article_list = article_list.filter(create_time__year=year, create_time__month=month)

res_category = models.Category.objects.filter(blog=user.blog).annotate(num=Count('article__id')).values_list(
'name', 'num', 'id')
res_tag = models.Tag.objects.filter(blog=user.blog).annotate(num=Count('article__id')).values_list('name',
'num', 'id')
res_month = models.Article.objects.filter(blog=user.blog).annotate(month=TruncMonth('create_time')).values(
'month').annotate(c=Count('id')).order_by('-month').values_list('month', 'c')

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

3 側邊欄inclusion_tag

# 步驟
-在app下建立一個包,templatetags
-任意新建一個py檔案my_tag.py
-匯入library
register = library.Library()
-寫一個函式,使用inclusion_tag裝飾
@register.inclusion_tag('left.html')
def left(username):
user = models.UserInfo.objects.filter(username=username).first()
res_category = models.Category.objects.filter(blog=user.blog).annotate(num=Count('article__id')).values_list(
'name', 'num', 'id')
res_tag = models.Tag.objects.filter(blog=user.blog).annotate(num=Count('article__id')).values_list('name',
'num', 'id')
res_month = models.Article.objects.filter(blog=user.blog).annotate(month=TruncMonth('create_time')).values(
'month').annotate(c=Count('id')).order_by('-month').values_list('month', 'c')

return {'name':username,'res_category': res_category, 'res_tag': res_tag, 'res_month': res_month}

-寫一個模板
<div>
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">我的標籤</h3>
</div>
<div class="panel-body">
{% for tag in res_tag %}
<p><a href="/{{ name }}/tag/{{ tag.2 }}.html">{{ tag.0 }}({{ tag.1 }})</a></p>
{% 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="/{{ name }}/category/{{ category.2 }}.html">{{ category.0 }}({{ category.1 }})</a></p>
{% endfor %}


</div>
</div>
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">隨筆檔案</h3>
</div>
<div class="panel-body">
{% for month in res_month %}
<p>
<a href="/{{ name }}/archive/{{ month.0|date:'Y/m' }}.html">{{ month.0|date:'Y年m月' }}({{ month.1 }})</a>
</p>
{% endfor %}
</div>
</div>
</div>

-使用,在指定的位置
{% load mytag %}
{% left name %}

4 點贊點踩樣式

html

<div id="div_digg">
<div class="diggit action">
<span class="diggnum" id="digg_count">{{ article.up_num }}</span>
</div>
<div class="buryit action">
<span class="burynum" id="bury_count">{{ article.down_num }}</span>
</div>
<div class="clear"></div>
<div class="diggword" id="digg_tips" style="color: red;">
</div>
</div>

css

#div_digg {
float: right;
margin-bottom: 10px;
margin-right: 30px;
font-size: 12px;
width: 125px;
text-align: center;
margin-top: 10px;
}

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

.buryit {
float: right;
margin-left: 20px;
width: 46px;
height: 52px;
background: url(/static/img/down.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;
}

5 點贊點踩功能完成

js

<script>
$(".action").click(function () {
var is_up = $(this).hasClass('diggit')
var span = $(this).children('span')
$.ajax({
url: '/upanddown/',
method: 'post',
data: {
article_id: '{{ article.id }}',
is_up: is_up,
csrfmiddlewaretoken: '{{ csrf_token }}'
},
success: function (data) {
console.log(data)
$('#digg_tips').html(data.msg)
if (data.code == 100) {
//點贊或者點踩的數字加一
var num = Number(span.html()) + 1
span.html(num)
}

}
})

})
</script>

後端

def upanddown(request):
res = {'code': 100, 'msg': ''}
if request.user.is_authenticated:
# article表中數字加1,在點贊點踩表中記錄一條
# 這個人對該文章只能點贊或者點踩一次
# 先查一下,如果有記錄了,就不能再點了
article_id = request.POST.get('article_id')
user_id = request.user.id
is_up = request.POST.get('is_up') # is_up是一個字串
print(type(is_up))
# if is_up=='true':
# is_up=True
# else:
# is_up = False
is_up=json.loads(is_up)
print(type(is_up))
res_1 = models.UpAndDown.objects.filter(article_id=article_id, user_id=user_id).count()
if res_1:
res['code'] = 101
res['msg'] = '已經點過了'
else:
with transaction.atomic():
models.UpAndDown.objects.create(article_id=article_id, user_id=user_id, is_up=is_up)
if is_up:
models.Article.objects.filter(pk=article_id).update(up_num=F('up_num') + 1)
res['msg'] = '點贊成功'
else:
models.Article.objects.filter(pk=article_id).update(down_num=F('down_num') + 1)
res['msg'] = '點踩成功'

else:
res['code'] = 109
res['msg'] = '請先<a href="/login/">登入</a>'
return JsonResponse(res)