BBS - 文章详细页、点赞、踩灭

一、文章详细页

 

文章详细页:
1.链接:
<div><h5><a href="/blog/{{ article.user.username }}/articles/{{ article.pk }}">{{ article.title }}</a></h5></div>

2.url分配:
re_path('(?P<username>\w+)/articles/(?P<article_id>\d+)/$',views.article_detail),

# 注意放在上面,否则下面得会覆盖上面得!
re_path('(?P<username>\w+)/articles/(?P<article_id>\d+)/$',views.article_detail),
re_path('(?P<username>\w+)/$',views.homesite)

3.模板继承:
因为 homesite 与 article_detail 整体页面样式,一样,只有内容部分不一样!!
继承,只传样式,没数据,怎么办? (include_tag)

知识点:
1.inclue 没有盒子得概念,某一块html直接拿来用!
{% include 'menu.html' %}

2.extends 可重写,可复用,有盒子得概念,整个页面继承.
{% extends 'base.html' %}

3.自定义标签
/blog/templatetags/my_tags.py
from django import template
register = template.Library()

@register.simple_tag
def mul(x,y):
return x*y

4.include_tag (自定义标签生成了html)
# 将 模板与数据 结合起来 (如果写函数也可以传数据,但是将模板与数据分开了)
/templatetags/my_tags.py

{% load my_tags %}
{% get_menu username %}

@register.inclusion_tag('menu.html')
def get_menu(username):
...
return {} 返回字典 去渲染 menu.html

作用:
include_tag 能解决复用问题,数据重复问题; 既有数据处理,又有模板渲染!

# -*- coding:utf-8 -*-

from django import template

register = template.Library()


@register.simple_tag
def mul(x,y):
    return x*y

from blog.models import *

@register.inclusion_tag('menu.html')
def get_menu(username):
    # 当前站点得用户对象
    user = UserInfo.objects.filter(username=username).first()
    blog = user.blog

    # 查询站点所有每一个分类 以及 对应得文章数 分组!!
    from django.db.models import Count

    # 查询站点所有每一个分类 以及 对应得文章数 分组!!
    cate_list = Category.objects.filter(blog=blog).annotate(count = Count('article')).values('title','count')

    # 每一个标签以及对应得文章数
    tag_list = Tag.objects.filter(blog=blog).annotate(count = Count('article')).values_list('title','count')

    # 查询每一个年月 日期 查询 统计
    date_list = Article.objects.filter(user=user).extra(select={"create_ym":"DATE_FORMAT(create_time,'%%Y-%%m')"}).values('create_ym').annotate(c = Count('nid')).values_list('create_ym','c')

    return {'username':username,'cate_list':cate_list,'tag_list':tag_list,'date_list':date_list}
my_tags.py
 
<div class="menu">
    <div class="panel panel-info">
        <div class="panel-heading">我的分类</div>
        <div class="panel-body">
            {% for cate in cate_list %}
                <p><a href="/blog/{{ username }}/cate/{{ cate.title }}">{{ cate.title }}({{ cate.count }})</a></p>
            {% endfor %}

        </div>
    </div>

    <div class="panel panel-success">
        <div class="panel-heading">我的标签</div>
        <div class="panel-body">
            {% for tag in tag_list %}
                <p><a href="/blog/{{ username}}/tag/{{ tag.0 }}">{{ tag.0 }}({{ tag.1 }})</a></p>
            {% endfor %}

        </div>
    </div>

    <div class="panel panel-danger">
        <div class="panel-heading">日期归档</div>
        <div class="panel-body">
            {% for date in date_list %}
                <p><a href="/blog/{{ username }}/archive/{{ date.0 }}">{{ date.0 }}({{ date.1 }})</a></p>
            {% endfor %}

        </div>
    </div>

</div>
menu.html

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>homesite</title>
    {% load my_tags %}

    <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.css">
    <link rel="stylesheet" href="/static/css/article_detail.css">
    <script src="/static/js/jquery-3.2.1.min.js"></script>
    <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
    <style type="text/css">
        *{padding: 0;margin: 0;}
        .header{ width: 100%; height: 40px; background-color: #336699;
        line-height: 40px; font-size: 16px; color: white;}
        .header p{ margin-left: 15px;}
    </style>

</head>
<body>

<div class="header">
    <p class="title">{{ blog.title }}</p>
</div>

<div class='container'>
    <div class="col-md-3">

        {% get_menu username %}

    </div>
    <div class="col-md-8">
        {% block content %}

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


</body>
</html>
base.html

 

{% extends 'base.html' %}

{% block content %}
    {% load my_tags %}
    <div class="article_list">
        {% for article in article_list %}

            <div class="article_item">
                <div><h5><a href="/blog/{{ article.user.username }}/articles/{{ article.pk }}">{{ article.title }}</a></h5></div>
                <div class="row">
                    <div class="col-md-9 desc">
                        <p>{{ article.desc }}</p>
                    </div>
                </div>
                <div class="small">
                    发布于&nbsp;&nbsp;&nbsp;
                    <span>{{ article.create_time|date:'Y-m-d' }}</span>&nbsp;&nbsp;&nbsp;&nbsp;
                    <span class="glyphicon glyphicon-comment"></span>评论({{ article.comment_count }})&nbsp;&nbsp;&nbsp;
                    <span class="glyphicon glyphicon-thumbs-up"></span>赞({{ article.up_count }})
                </div>
            </div>
            <hr>

        {% endfor %}

    </div>
{% endblock content %}
homesite.html

 

def homesite(request,username,**kwargs):
    # 当前站点得用户对象
    user = UserInfo.objects.filter(username=username).first()
    if not user:
        return HttpResponse('404')
    # 当前站点对象
    blog = user.blog

    # 查询当前站点对应得文章,以及分类,标签,日期归档得文章
    if not kwargs:
        article_list = Article.objects.filter(user=user)
    else:
        condition = kwargs.get('condition')
        param = kwargs.get('param')
        if condition == 'cate':
            article_list = Article.objects.filter(user=user, category__title=param)
        elif condition == 'tag':
            article_list = Article.objects.filter(user=user, tags__title=param)
        else:
            year, month = param.split('-')
            article_list = Article.objects.filter(user=user).filter(create_time__year=year, create_time__month=month)

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

 

{% extends 'base.html' %}

{% block content %}

    <h3 class="text-center">{{ article.title }}</h3>
    <div class="content">
        {{ article.articledetail.content|safe }}
    </div>


    <input type="hidden" id="hid_article_pk" value="{{ article.pk }}">
    <div id="div_digg">
        <div class="diggit digg">
            <span class="diggnum" id="digg_count">{{ article.up_count }}</span>
        </div>
        <div class="buryit digg">
            <span class="burynum" id="bury_count">{{ article.down_count }}</span>
        </div>
    </div>
    <div id="digg_word" class="pull-right"></div>

{% csrf_token %}

<script src="/static/js/article_detail.js"></script>

{% endblock content%}
article_detail.html

 

def article_detail(request,username,article_id):
    user = UserInfo.objects.filter(username=username).first()
    blog = user.blog

    article = Article.objects.filter(pk=article_id).first()

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

 

4.文章详细内容:
<h3 class="text-center">{{ article.title }}</h3>
<div class="content">
{{ article.articledetail.content|safe }}
</div>

为什么要加 safe?
{{ article.articledetail.content|safe }},告诉django不要转义

django 框架会将标签转义!
库:
<h1>Hello world</h1>
django:
&lt;h1&gt;Hello world&lt;/h1&gt;
浏览器渲染后:
<h1>Hello world</h1>

django 得模板问题:遇到标签转译为特殊字符,发送给客户端。
防止用户存一些 js 如果交给浏览器就会加载,实现攻击,恶意破环!

然而,就不应该让标签,不合法得类似<script>入库,后续beautifulSoup会学!

5.个人 站点 样式(皮肤)不一样:
<link rel="stylesheet" href="/static/theme/{{ blog.theme }}">

 

二、点赞、踩灭

    

 


注意点:
1.
在js中使用模板{{}} 加"", 不加""就当作变量了,找不到。
if("{{ request.user.username }}"){}
      

2.
ajax实现,两个按钮绑定一个点击事件。
前端:
var is_up = $(this).hasClass('diggit'); # true false
后台:
is_up = json.loads(request.POST.get('is_up')) # 变成 boolean 因为是str

    3.
      from django.db import transaction
      try:
       with transaction.atomic(): # 事务!同进退,数据同步!!

      是点赞还是踩灭? 自+1 更新时 F 查询得应用

       ArticleUpDown.objects.create(is_up=is_up,article_id=article_id,user_id=user_id)
       if is_up:
       Article.objects.filter(pk=article_id).update(up_count = F("up_count") + 1)
      else:
      Article.objects.filter(pk=article_id).update(down_count = F("down_count") + 1)

      except Exception as e:
      需要返回上一次得 点击情况:

      res['state'] = False
      res['first_operate'] = ArticleUpDown.objects.filter(article_id=article_id,user_id=user_id).first().is_up
        
    4.code:

<script src="/static/js/article_detail.js"></script>

    <input type="hidden" id="hid_article_pk" value="{{ article.pk }}">
    <input type="hidden" id="hid_username" value="{{ request.user.username }}">

    <div id="div_digg">
        <div class="diggit digg">
            <span class="diggnum" id="digg_count">{{ article.up_count }}</span>
        </div>
        <div class="buryit digg">
            <span class="burynum" id="bury_count">{{ article.down_count }}</span>
        </div>
    </div>
    <div id="digg_word" class="pull-right"></div>

import json
from django.http import JsonResponse
from django.db.models import F
def poll(request):
    is_up = json.loads(request.POST.get('is_up'))  # 得变成 boolean
    article_id = request.POST.get('article_id')
    user_id = request.user.pk
    res = {'state':True}

    from django.db import transaction
    try:
        with transaction.atomic():  # 事务
            ArticleUpDown.objects.create(is_up=is_up,article_id=article_id,user_id=user_id)
            if is_up:
                Article.objects.filter(pk=article_id).update(up_count = F("up_count") + 1)
            else:
                Article.objects.filter(pk=article_id).update(down_count = F("down_count") + 1)

    except Exception as e:
        res['state'] = False
        res['first_operate'] = ArticleUpDown.objects.filter(article_id=article_id,user_id=user_id).first().is_up
    return JsonResponse(res)

 

$('#div_digg .digg').click(function () {

    var username = $('#hid_username').val();
    if(username){
        var is_up = $(this).hasClass('diggit');
        var article_id = $('#hid_article_pk').val();
        var csrfmiddlewaretoken = $('input[name="csrfmiddlewaretoken"]').val();

        $.ajax({
            url:'/blog/poll/',
            type:'post',
            data:{
                is_up:is_up,
                article_id:article_id,
                csrfmiddlewaretoken:csrfmiddlewaretoken
            },
            success:function (data) {
                if(data.state){
                    // 赞或者灭 成功
                    if(is_up){
                        var val = parseInt($('#digg_count').text())+1;
                        $('#digg_count').text(val)

                    }else{
                        var val = parseInt($('#bury_count').text())+1;
                        $('#bury_count').text(val)
                    }

                }else{
                    // 重复操作 失败
                    console.log(data.first_operate);
                    if(data.first_operate){
                        $('#digg_word').html('您已经推荐过').css({"color":"red","margin-right":"-111px",'margin-top':"75px"})
                    }else{
                        $('#digg_word').html('您已经反对过').css({"color":"red","margin-right":"-111px",'margin-top':"75px"})
                    }

                }
            }

        })

    }else{
        location.href = '/login/'
    }

});
article_detail.js

 

知识点:

1.js 注意事项:

if(){ # 什么时候为 true / false ?
}else{
}
1.  
if([]){
alert(123)
}
弹, [] 空对象, object 对于对象 boolean 是真!!

2.
if({}){
alert(456)
}
弹, {} 空对象,object 对于对象 boolean 是真!

3.
if(""){
alert(789)
}
不弹

对于 js 除了""外,其它得都为对象,

4.
if("999"){
alert(789)
}
有值就为 真

2.js与模板语言:   
js 可以写模板语言{{}},但是要写到 html 里面。 "{{ }}" render 就可以渲染!

但是:写在静态文件中:
<script src="/static/js/test.js"></script>
不能使用 {{}} 模板语言!
alert("{{ name }}")

因为:没有任何过程去渲染!!
js是浏览器再发一次请求!

可以:
<input id="hid_name" type="hidden" value={{name}}>
js:
var val = $('#hid_name').val()

 

 
posted @ 2018-06-06 10:37  Alice的小屋  阅读(557)  评论(1编辑  收藏  举报