一、文章详细页

文章详细页:
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('')
# 当前站点对象
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()
 

BBS - 文章详细页、点赞、踩灭的更多相关文章

  1. python 全栈开发,Day82(点赞和踩灭,用户评论)

    一.点赞和踩灭 样式 先来做样式,修改article_detail.html,增加div_digg的div {% extends "base.html" %} {% block c ...

  2. BBS之文章详情页搭建

    博客评论相关 博客文章详情页搭建 {% extends 'base.html' %} {% block css %} <style> #div_digg { float: right; m ...

  3. BBS论坛 文章详情、点赞、评论

    六.文章详情.点赞.评论 文章详情页面: def article_detail(request, username, article_id): # user_obj = models.UserInfo ...

  4. BBS项目分布搭建三(个人站点时间归档补充,实现侧边栏跳转、无线级分类、实现文章详情页展示功能)

    BBS项目分布搭建三(个人站点时间归档补充,) 1. 个人站点时间归档 """ settings.py设置最好更改以下: LANGUAGE_CODE = 'zh-hans ...

  5. we7调用模板如何区分栏目页与详细页

    <a href='/xsdt/0000-00-00-00.html?id=<%# Eval("ID")%>'> 0000-00-00-00.html传参数来 ...

  6. wx小程序-列表详细页点击跳转!

    1.因为template 只是单纯的占位符,所以事件要写在外层view上面 2.通过自定义属性来判断 跳转的是那篇文章  自定义属性    (data-自定义名称 ) 3. 执行 onpostTap方 ...

  7. python 全栈开发,Day81(博客系统个人主页,文章详情页)

    一.个人主页 随笔分类 需求:查询当前站点每一个分类的名称以及对应的文章数 完成这个需求,就可以展示左侧的分类 它需要利用分组查询,那么必须要会基于双下划线的查询. 基于双下划线的查询,简单来讲,就是 ...

  8. django博客项目8:文章详情页

    首页展示的是所有文章的列表,当用户看到感兴趣的文章时,他点击文章的标题或者继续阅读的按钮,应该跳转到文章的详情页面来阅读文章的详细内容.现在让我们来开发博客的详情页面,有了前面的基础,开发流程都是一样 ...

  9. HelloDjango 第 08 篇:开发博客文章详情页

    作者:HelloGitHub-追梦人物 文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 首页展示的是所有文章的列表,当用户看到感兴趣的文章时,他点击文章的标题或者继续阅读的按 ...

随机推荐

  1. circso 对数据进行可视化

    circos可以用来绘制圈图,能够对染色体上的数据进行可视化,首先需要一个染色体的文件 染色体的文件如下,每列之间空格分隔 chr - chr1 chr1 chr - chr2 chr2 chr - ...

  2. Hibernate学习(1):查询demo

    1.数据库(mysql)创建脚本 DROP TABLE IF EXISTS role; CREATE TABLE IF NOT EXISTS `role`( `id` ) NOT NULL AUTO_ ...

  3. Kubernetes1.1源码分析(二)

    3.controller-manager模块 在controller manager模块中有几个重要的结构体.当中包含EndpointController.ReplicationManager.GCC ...

  4. 动态提交使用jQuery 完成ajax 文件下载----后端php

    1.js代码 // Ajax 文件下载 //当不用传参时,可以将data去掉 jQuery.download = function(url, data, method){ // 获得url和data ...

  5. C语言对文件的操作函数用法详解2

    fopen(打开文件) 相关函数 open,fclose 表头文件 #include<stdio.h> 定义函数 FILE * fopen(const char * path,const  ...

  6. 面试题:谈谈如何优化MYSQL数据库查询

    1.优化数据类型 MySQL中数据类型有多种,如果你是一名DBA,正在按照优化的原则对数据类型进行严格的检查,但开发人员可能会选择他们认为最简单的方案,以加快编码速度,或者选择最明显的选择,因此,你可 ...

  7. day08<面向对象+>

    面向对象(代码块的概述和分类) 面向对象(代码块的面试题) 面向对象(继承案例演示) 面向对象(继承的好处和弊端) 面向对象(Java中类的继承特点) 面向对象(继承的注意事项和什么时候使用继承) 面 ...

  8. Android权限全记录(转)

    常用权限: 读写存储卡装载和卸载文件系统 android.permission.WRITE_EXTERNAL_STORAGE android.permission.READ_EXTERNAL_STOR ...

  9. SGA内存的优化

    查看SGA有关的系统参数即介绍 SQL> show parameter sga NAME TYPE VALUE ------------------------------------ ---- ...

  10. iOS - UITableView滚动到指定的cell并且选中

    UITableView //项目中遇到的 - (void)selectRowAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)a ...