Django实现文章按年月归档、点赞和评论、发送邮件
文章归档的实现
我们在创建文章时,会在数据库中存储文章创建的时间这样的字段,一般用的都是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>   
                    <span style="color: gray">{{ comment.create_time|date:"Y-m-d H:i" }}</span>   
                    <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 }}:
                               {{ 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>    <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 + '  </span><span>' +
username + '  </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实现文章按年月归档、点赞和评论、发送邮件的更多相关文章
- tornado web高级开发项目之抽屉官网的页面登陆验证、form验证、点赞、评论、文章分页处理、发送邮箱验证码、登陆验证码、注册、发布文章、上传图片
		本博文将一步步带领你实现抽屉官网的各种功能:包括登陆.注册.发送邮箱验证码.登陆验证码.页面登陆验证.发布文章.上传图片.form验证.点赞.评论.文章分页处理以及基于tornado的后端和ajax的 ... 
- 本博文将一步步带领你实现抽屉官网的各种功能:包括登陆、注册、发送邮箱验证码、登陆验证码、页面登陆验证、发布文章、上传图片、form验证、点赞、评论、文章分页处理以及基于tronado的后端和ajax的前端数据处理。
		本博文将一步步带领你实现抽屉官网的各种功能:包括登陆.注册.发送邮箱验证码.登陆验证码.页面登陆验证.发布文章.上传图片.form验证.点赞.评论.文章分页处理以及基于tronado的后端和ajax的 ... 
- BBS论坛  文章详情、点赞、评论
		六.文章详情.点赞.评论 文章详情页面: def article_detail(request, username, article_id): # user_obj = models.UserInfo ... 
- day74 bbs项目☞点赞与评论
		目录 一.文章详情展示 1 将侧边栏做成inclusion_tag 二.点赞点踩功能 三.评论功能 整体总结: 在出现bug的时候,先判断是前端bug还是后端bug,再判断bug错误类型,以及报错信息 ... 
- python requests 简单实现易班登录,自动点赞,评论,发表
		小编能力有限,本文纯属瞎编,如有雷同,你去打辅导员涩 一.前戏 有个操蛋,操蛋,操蛋的辅导员促使小编成长,原因:易班需要活跃度,辅导员安排班上每个人必须去易班上 写文章,写评论,发投票... 我觉得 ... 
- 微信小程序仿朋友圈功能开发(发布、点赞、评论等功能)
		微信小程序仿朋友圈功能开发(发布.点赞.评论等功能) 1.项目分析 项目整体分为三个部分 发布 展示 详情页 graph LR 朋友圈发布 --内容发布--> 内容展示 内容展示 --点击展示卡 ... 
- Atitit qzone qq空间博客自动点赞与评论工具的设计与实现
		Atitit qzone qq空间博客自动点赞与评论工具的设计与实现 Qzone发送评论的原理 首先,有个a标签, <a class="c_tx3" href="j ... 
- Selenium实现微博自动化运营:关注、点赞、评论
		目录 Selenium 是什么? 一.核心代码 二.步骤分解 1.打开浏览器 2.访问微博登录页 3.输入账号密码 4.点击登录 5.通过人机验证 6.打开我们的中公题库君首页 7.加一下关注 8.定 ... 
- Java爬虫Ins博主所有帖子的点赞和评论导出excel
		前言 某天朋友说,能不能帮忙扒下ins的博主帖子,要所有帖子的点赞和评论,我本来准备让会python的同事写的,最后还是自己顺手写了,本来一开始准备用nodejs或者js写的,想着前端本地测试代理和导 ... 
随机推荐
- Last Position of Target
			For a given sorted array (ascending order) and a target number, find the first index of this number ... 
- [CodeVs1515]跳(lucas定理+费马小定理)
			嘿嘿嘿好久没写数学题了,偶尔看到一道写一写... 题目大意:一个(n+1)*(m+1)[0<=n, m<=10^12,n*m<=10^12]的矩阵,C(0,0)=1,C(x,y)=C ... 
- 框架----Django内置Admin
			Django内置的Admin是对于model中对应的数据表进行增删改查提供的组件,使用方式有: 依赖APP: django.contrib.auth django.contrib.contenttyp ... 
- 驱动之DMA的介绍与应用20170210
			本文主要介绍的是DMA相关的知识,首先: 1)在实现DMA传输时,是由DMA控制器直接掌管总线,因此,存在着一个总线控制权转移问题.即DMA传输前,CPU要把 总线控制权交给DMA控制器,而在结束DM ... 
- hihocoder 1509异或排序
			描述 给定一个长度为 n 的非负整数序列 a[1..n] 你需要求有多少个非负整数 S 满足以下两个条件: (1).0 ≤ S < 2^60 (2).对于所有 1 ≤ i < n ,有 ( ... 
- struts的status属性
			struts2 <s:iterator> status属性 转载▼ iterator标签主要是用于迭代输出集合元素,如list set map 数组等,在使用标签的时候有三个属性值得我 ... 
- c++构造是否要加大括号
			笔者被这个问题困扰良久,终于下决心看个究竟.废话不多说,先上结论: 如果对象是原生类型,加大括号会保证生成对象被初始化(一般是0) 如果对象非原生类型,加大括号或者不加,效果是一样的,都会执行该类的默 ... 
- 查看git拉取地址
			在项目地址下面输入:git remote -v 即可查看到地址啦. 
- CF757 C hash
			一种数字可以变成另一种数,要求每组中变换前后各种数字数量不变,问方案数 对现有每组中的每个数字构造出现在各个组情况的序列,如2 出现在第一组和第二组各一次那么就要加入组别的标号1,2,出现重复次仍要加 ... 
- 认识单点登录cas
			么是单点登录?单点登录全称Single Sign On(以下简称SSO),是指在多系统应用群中登录一个系统,便可在其他所有系统中得到授权而无需再次登录,包括单点登录与单点注销两部分 1.登录 相比于单 ... 
