文章详情页左侧边栏数据复用

文章详情页和个人站点的左侧边栏的内容格式都是一样的,从个人站点路由和文章详情路由进入到网页,侧边栏显示的内容是一模一样,解决方案:
方案一:
写一个home_site.html和article_detail.html建立一个新的母版base.html,两者继承base.html,在将所需的数据从对应的视图函数中传入即可。这只是解决了html代码重复问题。视图函数代码的问题是,在文章详情页和个人站点的视图函数中都要获取相同的数据,存在了数据代码冗余问题。
方案二:
利用inclusion_tag来解决方案一中的代码冗余。将样式和数据整合为一个整体,在返回到html中。

inclusion_tag方案设计

  1. 在对应应用下创建templatetags文件夹,文件夹的名字必须为这个。
  2. 在templatetags文件夹下创建my_tags.py文件,这个文件的名字可以随意。
  3. 在settings.py文件中添加my_tags的配置
    TEMPLATES = [
    {'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [os.path.join(BASE_DIR, 'templates')],'APP_DIRS': True,'OPTIONS': {'context_processors': ['django.template.context_processors.debug','django.template.context_processors.request','django.contrib.auth.context_processors.auth','django.contrib.messages.context_processors.messages',],'libraries':{"my_tags": "blog.templatetags.my_tags",},},},
    

]
```
准备工作完毕,下面添加正式代码

代码

前端代码:
classification.html

<div class="panel panel-warning"><div class="panel-heading">我的标签</div><div class="panel-body">{% for tag in tag_list %}<p><a href="/{{ username }}/tag/{{ tag.title }}/">{{ tag.title }}({{ tag.c }})</a></p>{% endfor %}</div>
</div>
<div class="panel panel-danger"><div class="panel-heading">我的分类</div><div class="panel-body">{% for category in category_list %}<p><a href="/{{ username }}/category/{{ category.title }}/">{{ category.title }}({{ category.c }})</a></p>{% endfor %}</div>
</div>
<div class="panel panel-info"><div class="panel-heading">随笔归档</div><div class="panel-body">{% for date in date_list %}<p><a href="/{{ username }}/archive/{{ date.month|date:'Y-m' }}/">{{ date.month|date:'Y-m' }}({{ date.c }})</a></p>{% endfor %}</div>
</div>

base.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="/static/css/bootstrap.min.css"><script src="/static/js/jquery.min.js"></script><script src="/static/js/bootstrap.min.js"></script><style>*{margin: 0;padding: 0}.header{width:100%;height:60px;background-color: #369;}.header .title{font-size: 18px;font-weight: 100;line-height: 60px;color: white;margin-left: 15px;margin-top: -10px;}.backend{float:right;color:white;text-decoration: none;margin-right:10px;margin-top:10px;font-size:14px;}.pub_info{margin-top:10px;color:dark-green;}</style>
</head>
<body>
<div class="header"><div class="content"><p class="title"><span class="">{{ blog.title }}</span><a href="" class="backend">管理</a></p></div>
</div>
<div class="container"><div class="row"><div class="col-md-3">{% load my_tags %}{% get_classification_style username %}</div><div class="col-md-9">{% block content %}{% endblock %}</div></div>
</div>
</body>
</html>

home_site.html

{% extends 'base.html' %}{% block content %}<div class="article_list">{% for article in article_list %}<div class="article_item clearfix"><h5><a href="">{{ article.title }}</a></h5><div class="article-desc">{{ article.desc }}</div><div class="small pub_info pull-right"><span><a href="">{{ article.user.username }}</a></span>&nbsp;&nbsp;<span>发布于&nbsp;&nbsp;{{ article.create_time|date:"Y-m-d H:i" }}</span>&nbsp;&nbsp;&nbsp;<span class="glyphicon glyphicon-comment"></span>评论({{ article.comment_count }})&nbsp;&nbsp;<span class="glyphicon glyphicon-thumbs-up"></span>点赞({{ article.up_count }})</div></div><hr>{% endfor %}</div>
{% endblock %}

article_detail.html

{% extends 'base.html' %}

后端代码:

# urls.py
"""cnblog URL ConfigurationThe `urlpatterns` list routes URLs to views. For more information please see:https://docs.djangoproject.com/en/1.10/topics/http/urls/
Examples:
Function views1. Add an import:  from my_app import views2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views1. Add an import:  from other_app.views import Home2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf1. Import the include() function: from django.conf.urls import url, include2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from django.views.static import serve
from cnblog import settings
from blog import views as blog_views
urlpatterns = [url(r'^admin/', admin.site.urls),url(r'^$', blog_views.index),url(r'^login/', blog_views.login, name="login"),url(r'^logout/', blog_views.logout, name="logout"),url(r'^register', blog_views.register, name="register"),url(r'^index/', blog_views.index, name="index"),url(r'^get_validCode_img', blog_views.get_validCode_img),# media 配置url(r'media/(?P<path>.*)$', serve, {"document_root": settings.MEDIA_ROOT}),# 个人站点url(r'^(?P<username>\w+)/$', blog_views.home_site),# 个人站点跳转url(r'^(?P<username>\w+)/(?P<condition>tag|category|archive)/(?P<param>.*)/$', blog_views.home_site),# 文章详情url(r'^(?P<username>\w+)/article/(?P<article_id>\d+)/$', blog_views.article_detail),
]
# views.py
def home_site(request, username, **kwargs):user = UserInfo.objects.filter(username=username).first()# 判断用户是否存在if not user:# 返回404return render(request, 'not_found.html')# 查询出当前用户对应的站站点信息blog = user.blog# 基于对象的所有文章查询# article_list = user.article_set.all()# 基于 __ 查询article_list = models.Article.objects.filter(user=user)if kwargs:condition = kwargs.get('condition')param = kwargs.get('param')if condition == 'category':# article_list = models.Article.objects.filter(user=user, category__title=param)article_list = article_list.filter(category__title=param)elif condition == 'tag':# article_list = models.Article.objects.filter(user=user, tags__title=param)article_list = article_list.filter(tags__title=param)elif condition == 'archive':year, month = param.split('-')print(year, month)# article_list = models.Article.objects.filter(#     user=user,#     create_time__year=year,#     create_time__month=month# )article_list = article_list.filter(create_time__year=year, create_time__month=month)else:passreturn render(request, 'home_site.html', {'username': username, 'blog': blog, 'article_list': article_list})def article_detail(request, username, article_id):return render(request, 'article_detail.html', locals())
# my_tags.py
from django import template
from django.db.models.functions import TruncMonth
from django.db.models import Count
from blog import modelsregister = template.Library()@register.inclusion_tag("classification.html")
def get_classification_style(username):print(username)user = models.UserInfo.objects.filter(username=username).first()blog = user.blogcategory_list = models.Category.objects.filter(blog=blog).annotate(c=Count('article__title')).values('title', 'c')tag_list = models.Tag.objects.filter(blog=blog).annotate(c=Count('article__title')).values('title', 'c')date_list = models.Article.objects.filter(user=user).annotate(month=TruncMonth('create_time')).values('month').annotate(c=Count('pk')). \values('month', 'c')return {'user': user, 'blog': blog, 'category_list': category_list, 'tag_list': tag_list, 'date_list': date_list, 'username': username}

知识点

模板继承
inclusion_tag

执行流程

  1. 访问http://127.0.0.1:8080/lxt/
  2. 进入路由层进行匹配,匹配到url(r’^(?P\w+)/$’, blog_views.home_site)
  3. 进入对应视图层blog_views.home_site,返回home_site.html网页
  4. 在home_site.html中继承了base.html,先加载base.html
  5. base.html中执行了inclusion_tag的语法{% load my_tags %}
    {% get_classification_style username %}
  6. 加载get_classification_style,执行get_classification_style中的代码,将执行完拿到的数据返回到@register.inclusion_tag(“classification.html”)对应的classification.html进行数据和样式整合。
  7. 将数据和样式整合之后的html代码返回到调用get_classfication_style的地方
  8. 在base.html中将样式和数据整合为一体的html代码展示到调用处
  9. home_site.html网页完成加载

每次加载base.html时,其他网页的视图函数就不需要重复传入左侧边栏的数据内容,解决了代码冗余。

style样式抽出

对base.html中的style样式提出到单独的css文件隔离出home_site.css和article_detail.css样式

代码

home_site.css

*{margin: 0;padding: 0
}
.header{width:100%;height:60px;background-color: #369;
}
.header .title{font-size: 18px;font-weight: 100;line-height: 60px;color: white;margin-left: 15px;margin-top: -10px;
}
.backend{float:right;color:white;text-decoration: none;margin-right:10px;margin-top:10px;font-size:14px;
}
.pub_info{margin-top:10px;color:dark-green;
}

article_detail.css

.article_info .title{margin-bottom: 20px;
}

base.html
引入两个css样式

<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="/static/css/bootstrap.min.css"><link rel="stylesheet" href="/static/css/home_site.css"><link rel="stylesheet" href="/static/css/article_detail.css"><script src="/static/js/jquery.min.js"></script><script src="/static/js/bootstrap.min.js"></script></head>

点赞样式构建

代码

article_detail.css

.article_info .title{margin-bottom: 20px;
}
#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/fonts/upup.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/fonts/downdown.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;
}

article_detail.html

<div id="div_digg"><div class="diggit"><span class="diggnum" id="digg_count">0</span></div><div class="buryit"><span class="burynum" id="bury_count">0</span></div><div class="clear"></div><div class="diggword" id="digg_tips" style="color: red;"></div>
</div>

效果预览

文章点赞

给推荐和反对绑定同一个点击事件,当点击推荐的时候传递到后端的是True,当点击反对的时候传递到后端的是False。
给div_digg下的两个div标签起同一个名字添加事件。
一个用户只能赞同或者反对一次,再次点击会提示已经操作过了,不能重复操作。

代码

article_detail.html

<div id="div_digg">{% csrf_token %}<div class="diggit action"><span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span></div><div class="buryit action"><span class="burynum" id="bury_count">{{ article_obj.down_count }}</span></div><div class="clear"></div><div class="diggword" id="digg_tips" style="color: red;"></div>
</div><script>$('#div_digg .action').click(function (){var is_up = $(this).hasClass("diggit")$.ajax({url:"/digg/",type:"post",data:{"csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val(),"is_up":is_up,"article_id":{{ article_obj.pk }}},success: function (data){console.log(data.state, data.handle)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{if (data.handle){$('#digg_tips').html("您已经推荐过")}else{$('#digg_tips').html("您已经反对过")}setTimeout(function(){$('#digg_tips').html("")}, 1000)}}})})
</script>

views.py

def digg(request):article_id = request.POST.get("article_id")is_up = request.POST.get("is_up")  # 拿到的是一个字符串is_up = json.loads(is_up)response = {'state': True, 'handle': None}obj = models.ArticleUpDown.objects.filter(user=request.user, article_id=article_id).first()if not obj:# 用户没有进行赞同或者反对,生成新的数据models.ArticleUpDown.objects.create(user=request.user, article_id=article_id, is_up=is_up)queryset = models.Article.objects.filter(pk=article_id)if is_up:# 用户点击赞同,对article中的upcount进行加1queryset.update(up_count=F("up_count")+1)else:queryset.update(down_count=F("down_count")+1)else:response['state'] = False  # state 代表用户已经进行过赞同或者反对了response['handle'] = obj.is_up  # handle 代表用户进行的是赞同还是反对return JsonResponse(response)

urls.py

url(r'^digg/', blog_views.digg),

效果展示

django博客项目-文章详情页功能相关推荐

  1. php博客系统 加载评论,Yii实现单用户博客系统文章详情页插入评论表单的方法...

    本文实例讲述了Yii实现单用户博客系统文章详情页插入评论表单的方法.分享给大家供大家参考,具体如下: action部分: function test($objs) { $objs->var=10 ...

  2. 【博客项目】—用户删除功能(十二)

    [博客项目]-用户删除功能(十二)

  3. 【博客项目】—用户修改功能(十一)

    [博客项目]-用户修改功能(十一)

  4. 【博客项目】—用户新增功能(九)

    [博客项目]-用户新增功能(九) 此时的数据库里面已经新增了一个用户

  5. 【博客项目】—登录验证功能实现( 五)

    [博客项目]-登录验证功能实现( 五)

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

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

  7. 基于Spring Boot和Vue3的博客平台文章详情与评论功能实现

    在前面的教程中,我们已经实现了基于Spring Boot和Vue3的发布.编辑.删除文章功能以及文章列表与分页功能.本教程将引导您实现博客平台的文章详情与评论功能. 整个实现过程可以分为以下几个步骤: ...

  8. SpringBoot个人博客项目搭建—前端页面功能介绍(一)

    SpringBoot个人博客-前端页面功能介绍(一) 项目首页地址:https://blog.csdn.net/weixin_45019350/article/details/108869025 一. ...

  9. 在线博客系统——文章详情(redis incr自增实现增加阅读数和评论数)

    目录 文章详情 接口说明 编码实现 Controller控制层 Service业务逻辑层 前端测试 redis incr自增实现浏览量 Redis配置类 Redis工具类 Dao持久层准备 Mappe ...

最新文章

  1. 焦油坑和人月神话--人月笔记1
  2. c mysql 设置字符集_C语言如何查看和修改MySQL使用的字符集
  3. python中cgi到底是什么_什么是CGI?详细介绍Python CGI编程
  4. uni-app之新建项目无模板选择以及点击创建后一直卡住不动
  5. 中国式离婚中,林与宋离婚成为定局的时刻
  6. 笨办法学 Python · 续 练习 40:SQL 读取
  7. web developer tips (38):如何用请求失败记录追踪重写规则
  8. UnityShader18:立方体贴图(上)
  9. C#.NET 通用权限管理系统中的数据集权限设置实现参考界面(商业化成熟权限管理系统,提供全部源码)...
  10. 通过方法将汉字转成拼音
  11. Zabbix实现自动发现端口并监控
  12. 机械设计基础复习重点
  13. 计算机常用的采样频率,采样频率
  14. 计算机怎么格式化硬盘,电脑格式化硬盘 电脑格式化硬盘要怎么操作
  15. 时间固定效应和个体固定效应的选择_固定效应模型必须同时控制时间和个体吗?...
  16. Nvidia GPU虚拟化
  17. 2022081班李亚楠20220902
  18. SZA-Template
  19. 多边形的扫描转换算法——扫描线算法(计算机图形学)
  20. 如何取消Office 正版增值验证

热门文章

  1. commonjs 与 esm 的区别
  2. Compose 横竖屏切换时状态如何保存?rememberSaveable 实现原理分析
  3. pandas爬取数据示例网页
  4. Linux 文件/文件夹无法删除问题解决方案
  5. java工程积累——项目管理:破窗理论
  6. Python 设置numpy不以科学计数法保存和显示的方法
  7. 【码农话健身】健身房练胸窍门
  8. 【服务器数据恢复】服务器5盘RAID5重建为4盘RAID5后的数据恢复案例
  9. 二、T100多角贸易实战
  10. 基于Java图书馆管理系统、JAVA图书借阅系统设计与实现 毕业设计开题报告