文章归档的实现

我们在创建文章时,会在数据库中存储文章创建的时间这样的字段,一般用的都是datetime类型,记录文章创建的年月日和时分秒,所以我们直接使用文章的创建时间分类是无法实现文章的按年月归档的,因为每一篇文章的时间是不一样的,所以我们在使用ORM查询时就无法做到按年月分类的需求,这是就需要额外的SQL语句来实现,在SQL语句中有一个很重的时间格式化的方法:date_format

  我们可以使用ORM中执行SQL语句原生用法的方法:extra

from blog import models
from django.db.models import Count
#假设我们得到一个user对象 文章表中有一个create_time 字段
achive = models.Article.objects.filter(user=user).extra(
select={"archive":"date_format(create_time,'%%Y-%%m')" }
).values("archive").annotate(c=Count('pk')).values("archive","c") #"pk" 在Django中代指表的主键

urls.py的配置

from django.conf.urls import url
from blog import views urlpatterns = [
url(r'^(\w+)/archive/(.+)/$',views.home), ]

views.py

                try:
year, mouth = args[1].split('-')
logger.debug('年:{} 月:{}'.format(year, mouth))
article_list = models.Article.objects.filter(user=user).filter(create_time__year=year,
create_time__month=mouth)
except Exception as e:
logger.error(str(e))
return HttpResponse('')

备注:使用Django时,默认使用的UTC时间,而中国的时区为东八区,所以会在查询时间时带上一个+8的字样,所以通过fliter查找字段时,直接等于year或者month是无法查出需要的对象的,这是我们需要在settings.py文件中,修改一个参数:USE_TZ = True  改为False 就可以了。

点赞的实现

点赞部分的HTML实现

    <div class="clearfix">
<div id="div_digg">
<div class="diggit">
<span class="diggnum" id="digg_count">{{ article.up_count }}</span>
</div>
<div class="buryit">
<span class="burynum" id="bury_count">{{ article.down_count }}</span>
</div>
<div class="clear"></div>
<div class="diggword" id="digg_tips" style="color: red;"></div>
</div>
</div>
// 备注;如果js的实现是作为一个静态文件导入时,需要在HTML页面中隐藏一个标签,这个标签存储我们在静态文件中需要的值
<div class="info" article_id="{{ article.pk }}" username="{{ request.user.username }}" style="display: none"></div>
 

备注:在bootstarp中会自带一个清除父标签塌陷的样式类方法  (class="clearfix")

点赞的相关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/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/img/downdown.gif') no-repeat;
text-align: center;
cursor: pointer;
margin-top: 2px;
padding-top: 5px;
} .clear {
clear: both;
}

点赞效果实现的相关css样式

点赞帮点事件并发ajax请求

$("#div_digg .action").click(function () {
if ($(".info").attr("username")) { // 点赞或踩灭 通过判断有无某个样式类来区分是点赞还是踩,以点赞中的diggit样式类参考,如果为点赞,则返回true,为踩,返回false
var is_up = $(this).hasClass("diggit");
var article_id = $(".info").attr("article_id"); $.ajax({
url: "/blog/up_down/",
type: "post",
data: {
is_up: is_up,
article_id: article_id,
csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
},
success: function (data) {
// console.log(data);
if (data.state) {// 对当前文章首次赞或者灭成功 if (is_up) {
var val = $("#digg_count").text();
val = parseInt(val) + 1;
$("#digg_count").text(val);
} else {
var val = $("#bury_count").text();
val = parseInt(val) + 1;
$("#bury_count").text(val);
}
}
else { // 重复提交 if (data.fisrt_action) {
$("#digg_tips").html("您已经推荐过");
} else {
$("#digg_tips").html("您已经反对过");
} setTimeout(function () {
$("#digg_tips").html("")
}, 1000)
}
}
})
}
else {
// 没有登录 就跳转登录
location.href = "/login/"
} });

静态文件版

点赞urls.py (ajax请求相关)

from django.conf.urls import url
from blog import views urlpatterns = [
url(r"up_down/",views.up_down),
]

点赞处理ajax请求的视图函数

def up_down(request):
article_id=request.POST.get('article_id')
is_up=json.loads(request.POST.get('is_up'))
user=request.user
response={"state":True}
try:
models.ArticleUpDown.objects.create(user=user,article_id=article_id,is_up=is_up)
models.Article.objects.filter(pk=article_id).update(up_count=F("up_count")+1)
except Exception as e:
response["state"]=False
response["fisrt_action"]=models.ArticleUpDown.objects.filter(user=user,article_id=article_id).first().is_up
return JsonResponse(response)

评论的实现

评论树和评论楼两种方式:

评论的相关路由

from django.conf.urls import url
from blog import views urlpatterns = [
url(r"comment/",views.comment),
url(r"comment_tree/(\d+)/",views.comment_tree),
]

评论的相关视图函数

def comment(request):

    print(request.POST)

    pid=request.POST.get("pid")
article_id=request.POST.get("article_id")
content=request.POST.get("content")
user_pk=request.user.pk
response={}
if not pid: #根评论
comment_obj=models.Comment.objects.create(article_id=article_id,user_id=user_pk,content=content)
else:
comment_obj=models.Comment.objects.create(article_id=article_id,user_id=user_pk,content=content,parent_comment_id=pid) response["create_time"]=comment_obj.create_time.strftime("%Y-%m-%d")
response["content"]=comment_obj.content
response["username"]=comment_obj.user.username return JsonResponse(response) def comment_tree(request,article_id): ret=list(models.Comment.objects.filter(article_id=article_id).values("pk","content","parent_comment_id"))
print(ret)
return JsonResponse(ret,safe=False)

评论的HTML相关

    <p>评论树</p>

    <div class="comment_tree">
// 评论树内容相关 </div>
<hr> <p>评论楼</p>
<p>评论列表</p>
<ul class="comment_list">
{% for comment in comment_list %}
<li class="list-group-item">
<div>
<a href="">#{{ forloop.counter }}楼</a> &nbsp;&nbsp;
<span style="color: gray">{{ comment.create_time|date:"Y-m-d H:i" }}</span> &nbsp;&nbsp;
<a href=""><span>{{ comment.user.username }}</span></a>
<a class="pull-right reply_btn" username="{{ comment.user.username }}"
comment_pk="{{ comment.pk }}"><span>回复</span></a>
</div>
{% if comment.parent_comment_id %}
<div class="pid_info well">
<p> {{ comment.parent_comment.user.username }}:
&nbsp;&nbsp;&nbsp;{{ comment.parent_comment.content }} </p>
</div>
{% endif %} <div class="con">
<p>
{{ comment.content }}
</p>
</div>
</li>
{% endfor %}
</ul> {% if request.user.username %}
<div class="div_comment">
<p>昵称:<input type="text" id="tbCommentAuthor" class="author" disabled="disabled" size="50"
value="{{ request.user.username }}"></p>
<p>评论内容</p>
<textarea name="" id="comment_content" cols="60" rows="10"></textarea>
<p>
<button id="comment_btn">提交评论</button>
</p> </div>
{% else %}
<a href="/login/">登录</a>
{% endif %}

评论的js实现

<script>
// 获取评论数据,展示评论树结构
$.ajax({
url: "/blog/comment_tree/" + '{{ article.pk }}/',
success: function (data) {
console.log(data); $.each(data, function (index, comment_dict) {
var s = '<div class="comment_item" comment_id=' + comment_dict.pk + '> <span class="content">' + comment_dict.content + '</span> </div>'
if (comment_dict.parent_comment_id) {
// 子评论
var perid=comment_dict.parent_comment_id;
$("[comment_id="+perid+"]").append(s);
}
else { // 根评论
$(".comment_tree").append(s);
}
}) }
}); // 提交评论
var pid = "";
$("#comment_btn").click(function () { var article_id = $(".info").attr("article_id");
var content = $("#comment_content").val();
if (pid) {
var index = content.indexOf("\n");
content = content.slice(index + 1)
} $.ajax({
url: "/blog/comment/",
type: "post",
data: {
article_id: article_id,
content: content,
pid: pid,
csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
},
success: function (data) {
console.log(data);
var create_time = data.create_time;
var content = data.content;
var username = data.username;
             if (arg.status){
         // 是根评论
var comment_li = '<li class="list-group-item"><div><span style="color: gray">' + create_time
            + '</span> &nbsp;&nbsp; <a href=""><span>' + username + '</span></a></div> <div class="con">
            <p> ' + content + ' </p> </div> </li>'; $(".comment_list").append(comment_li);
            }else{
          // 是子评论
          var parent_name = arg.parent_username;
          var par_content = arg.parent_content;
          var m = '<li class="list-group-item"><div><span>' + create_time + '&nbsp;&nbsp;</span><span>' +
        username + '&nbsp;&nbsp;</span>' + '</div><div class="well">'+parent_name+':'
              +par_content+'</div><div>' + content + '</div></li>';
        $(".list-group").append(m);
          }
            // 清空文本框 $("#comment_content").val('');
             // 清空pid pid = ""
            }
        })
    });
// 回复按钮事件
$(".list-group-item .reply_btn").click(function () {
$("#comment_content").focus();
var v = "@" + $(this).attr("username") + "\n"; $("#comment_content").val(v); //pid赋值 pid = $(this).attr("comment_pk") }) </script>

另外Django中也提供了发送邮件的方法,不需要我们直接使用email模块

from django.core.mail import send_mail

Django实现发邮件

1 首先去自己的邮箱申请,在设置里面找,申请开通smtp服务,我用的是163邮箱

2 在项目下settings.py中添加设置:

 1 # 配置邮箱发邮件的相关功能
2
3 #这一项是固定的
4 EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
5 # smtp服务的邮箱服务器 我用的是163
6 EMAIL_HOST = 'smtp.163.com'
7 # smtp服务固定的端口是25
8 EMAIL_PORT = 25
9 #发送邮件的邮箱
10 EMAIL_HOST_USER = 'xxxx@163.com'
11 #在邮箱中设置的客户端授权密码
12 EMAIL_HOST_PASSWORD = 'xxxx'
13 #收件人看到的发件人 <此处要和发送邮件的邮箱相同>
14 EMAIL_FROM = 'python<xxxx@163.com>'

3 配置好映射urls.py, 创建好视图,.... 这些步骤省略了.....找到相应视图后

4 在视图中调用如下函数 即可发送邮件:

 1 from django.conf import settings
2 from django.core.mail import send_mail
3 from django.http import HttpResponse
4 ...
5 def send(request):
6 msg='<a href="哈哈哈" target="_blank">点击激活</a>'
7 send_mail('标题','内容',settings.EMAIL_FROM,
8 '目标邮箱',
9 html_message=msg)
10 return HttpResponse('ok')

注意要 导入 settings模块,和send_email模块

调用send_mail() 函数即发送邮件,具体参数如下

send_mail( 标题,文字内容,发件邮箱,目的邮箱,html标签内容 )

Django实现文章按年月归档、点赞和评论、发送邮件的更多相关文章

  1. tornado web高级开发项目之抽屉官网的页面登陆验证、form验证、点赞、评论、文章分页处理、发送邮箱验证码、登陆验证码、注册、发布文章、上传图片

    本博文将一步步带领你实现抽屉官网的各种功能:包括登陆.注册.发送邮箱验证码.登陆验证码.页面登陆验证.发布文章.上传图片.form验证.点赞.评论.文章分页处理以及基于tornado的后端和ajax的 ...

  2. 本博文将一步步带领你实现抽屉官网的各种功能:包括登陆、注册、发送邮箱验证码、登陆验证码、页面登陆验证、发布文章、上传图片、form验证、点赞、评论、文章分页处理以及基于tronado的后端和ajax的前端数据处理。

    本博文将一步步带领你实现抽屉官网的各种功能:包括登陆.注册.发送邮箱验证码.登陆验证码.页面登陆验证.发布文章.上传图片.form验证.点赞.评论.文章分页处理以及基于tronado的后端和ajax的 ...

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

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

  4. day74 bbs项目☞点赞与评论

    目录 一.文章详情展示 1 将侧边栏做成inclusion_tag 二.点赞点踩功能 三.评论功能 整体总结: 在出现bug的时候,先判断是前端bug还是后端bug,再判断bug错误类型,以及报错信息 ...

  5. python requests 简单实现易班登录,自动点赞,评论,发表

    小编能力有限,本文纯属瞎编,如有雷同,你去打辅导员涩 一.前戏 有个操蛋,操蛋,操蛋的辅导员促使小编成长,原因:易班需要活跃度,辅导员安排班上每个人必须去易班上 写文章,写评论,发投票...  我觉得 ...

  6. 微信小程序仿朋友圈功能开发(发布、点赞、评论等功能)

    微信小程序仿朋友圈功能开发(发布.点赞.评论等功能) 1.项目分析 项目整体分为三个部分 发布 展示 详情页 graph LR 朋友圈发布 --内容发布--> 内容展示 内容展示 --点击展示卡 ...

  7. Atitit qzone qq空间博客自动点赞与评论工具的设计与实现

    Atitit qzone qq空间博客自动点赞与评论工具的设计与实现 Qzone发送评论的原理 首先,有个a标签, <a class="c_tx3" href="j ...

  8. Selenium实现微博自动化运营:关注、点赞、评论

    目录 Selenium 是什么? 一.核心代码 二.步骤分解 1.打开浏览器 2.访问微博登录页 3.输入账号密码 4.点击登录 5.通过人机验证 6.打开我们的中公题库君首页 7.加一下关注 8.定 ...

  9. Java爬虫Ins博主所有帖子的点赞和评论导出excel

    前言 某天朋友说,能不能帮忙扒下ins的博主帖子,要所有帖子的点赞和评论,我本来准备让会python的同事写的,最后还是自己顺手写了,本来一开始准备用nodejs或者js写的,想着前端本地测试代理和导 ...

随机推荐

  1. 信息收集利器——Nmap

    环境:kali2.0 常用的Nmap命令总结: 1.扫描单个IP地址 nmap 192.168.56.1 2.扫描一个网络中IP地址范围 nmap 192.168.56.1-255 3.扫描目标主机的 ...

  2. 最小生成树-----Prim算法与Kruskal算法(未完

    生成树(spanning tree):无向联通图的某个子图中,任意两个顶点互相都联通并且形成了一棵树,那么这棵树就叫做生成树. 最小生成树(MST,minimum spanning tree):如果为 ...

  3. Hive(三)hive的高级操作

    一.hive的各种join操作 语法结构:join_table:table_reference JOIN table_factor [join_condition]| table_reference ...

  4. 解题:SCOI 2014 方伯伯运椰子

    题面 很有趣的一道题,看起来是个神奇网络流,其实我们只要知道网络的一些性质就可以做这道题了 因为题目要求流量守恒,所以我们其实是在网络中搬运流量,最终使得总费用减小,具体来说我们可以直接把这种“搬运” ...

  5. 【莫队】【P3834】 【模板】可持久化线段树 1(主席树)

    大家好,我是个毒瘤,我非常喜欢暴力数据结构,于是我就用莫队+分块过了这个题 Solution 发现这个题静态查询资瓷离线,于是考虑莫队. 在这里简单介绍一下莫队: 将所有询问离线后,对原序列分块.按照 ...

  6. web项目引用tomcat中的jar

    web项目引用tomcat中的jar https://blog.csdn.net/zjsdrs/article/details/77868827 如下图所示

  7. Codeforces 578.C Weakness and Poorness

    C. Weakness and Poorness time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  8. Kubernetes - Deploy Guestbook example on Kubernetes

    This scenario explains how to launch a simple, multi-tier web application using Kubernetes and Docke ...

  9. libuv移植到ios

    libuv官网只提供了os x的编译方法,没有IOS的.既然os x和ios的系统内核差不多,并且编译工具都是xcode,那我们只要重新指定cpu架构,就可以编译出ios版的了. 1.安装python ...

  10. git相关网址

    git入门教程: 廖雪峰的官方网站 https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b00 ...