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">
发布于
<span>{{ article.create_time|date:'Y-m-d' }}</span>
<span class="glyphicon glyphicon-comment"></span>评论({{ article.comment_count }})
<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:
<h1>Hello world</h1>
浏览器渲染后:
<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 - 文章详细页、点赞、踩灭的更多相关文章
- python 全栈开发,Day82(点赞和踩灭,用户评论)
一.点赞和踩灭 样式 先来做样式,修改article_detail.html,增加div_digg的div {% extends "base.html" %} {% block c ...
- BBS之文章详情页搭建
博客评论相关 博客文章详情页搭建 {% extends 'base.html' %} {% block css %} <style> #div_digg { float: right; m ...
- BBS论坛 文章详情、点赞、评论
六.文章详情.点赞.评论 文章详情页面: def article_detail(request, username, article_id): # user_obj = models.UserInfo ...
- BBS项目分布搭建三(个人站点时间归档补充,实现侧边栏跳转、无线级分类、实现文章详情页展示功能)
BBS项目分布搭建三(个人站点时间归档补充,) 1. 个人站点时间归档 """ settings.py设置最好更改以下: LANGUAGE_CODE = 'zh-hans ...
- we7调用模板如何区分栏目页与详细页
<a href='/xsdt/0000-00-00-00.html?id=<%# Eval("ID")%>'> 0000-00-00-00.html传参数来 ...
- wx小程序-列表详细页点击跳转!
1.因为template 只是单纯的占位符,所以事件要写在外层view上面 2.通过自定义属性来判断 跳转的是那篇文章 自定义属性 (data-自定义名称 ) 3. 执行 onpostTap方 ...
- python 全栈开发,Day81(博客系统个人主页,文章详情页)
一.个人主页 随笔分类 需求:查询当前站点每一个分类的名称以及对应的文章数 完成这个需求,就可以展示左侧的分类 它需要利用分组查询,那么必须要会基于双下划线的查询. 基于双下划线的查询,简单来讲,就是 ...
- django博客项目8:文章详情页
首页展示的是所有文章的列表,当用户看到感兴趣的文章时,他点击文章的标题或者继续阅读的按钮,应该跳转到文章的详情页面来阅读文章的详细内容.现在让我们来开发博客的详情页面,有了前面的基础,开发流程都是一样 ...
- HelloDjango 第 08 篇:开发博客文章详情页
作者:HelloGitHub-追梦人物 文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 首页展示的是所有文章的列表,当用户看到感兴趣的文章时,他点击文章的标题或者继续阅读的按 ...
随机推荐
- UVa 10633 - Rare Easy Problem
题目:给定一个数N.去掉末尾的数变成M.如今已知N-M,确定N. 分析:数论.简单题. 设N = 10*a + b { 当中0 ≤ b ≤ 9 }.则M = a: N - M = N - a = 9* ...
- windowmasker 标记基因组中的重复序列和低复杂度序列
下载地址:ftp://ftp.ncbi.nlm.nih.gov/pub/agarwala/windowmasker/ 在这个目录下 其中windowmasker 为linux 平台的可执行文件 win ...
- Onject.Instantiate实例
该函数有两个函数原型: Object Instantiate(Object original,Vector3 position,Quaternion rotation); Onject Instant ...
- PHP中如何获取网站根目录物理路径
在php程序开发中经常需要获取当前网站的目录,我们可以通过常量定义获取站点根目录物理路径,方便在程序中使用. 下面介绍几种常用的获取网站根目录的方法. php获取网站根目录方法一: <?php ...
- MySQL(二)之服务管理与配置文件修改和连接MySQL
上一篇给大家介绍了怎么在linux和windows中安装mysql,本来是可以放在首页的,但是博客园说“安装配置类文件”不让放在首页.接下来给大家介绍一下在linux和windows下MySQL的一下 ...
- [转]查看处于被锁状态的表:v$locked_object dba_objects v$session all_objects v$sqlarea v$lock
oracle官网当一个用户发出select..for update的错作准备对返回的结果集进行修改时,如果结果集已经被另一个会话锁定,就是发生阻塞.需要等另一个会话结束之后才可继续执行.可以通过发出 ...
- 【R】array 2 string
paste(1:10, collapse = '') http://stackoverflow.com/questions/2098368/how-do-i-concatenate-a-vector- ...
- 设置同样字体大小,chrome浏览器有时字体偏大的解决办法(转)
本文是找了在网上搜了好久才找到非常棒的一篇文章,很好的解决了这个问题. 原文地址:https://github.com/amfe/article/issues/10 这个特性被称做「Text Auto ...
- ASP.NET MVC传递参数(model), 如何保持TempData的持久性
一看到此标题,相信你也会.因为路由是可以从URL地址栏传过去的. 但是Insus.NET不想在地址栏传递,还是一个条件是jQuery的Ajax进行POST的.Insus.NET不清楚别人是怎样处理的, ...
- About {DynamicResource {x:Static SystemColors.ControlBrushKey}}
from : http://blog.sina.com.cn/s/blog_749e42850100sahi.html 前提: <system:String x:Key="{Compo ...