文章归档的实现

我们在创建文章时,会在数据库中存储文章创建的时间这样的字段,一般用的都是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标签内容 )

最新文章

  1. Java之美[从菜鸟到高手演变]之HashMap、HashTable(转载)
  2. 从prompt输入10个人的年龄放入数组,将十个人的年龄求总和。
  3. HBASE的安装
  4. c#下winform的ftp上传
  5. vue 绑定样式的几种方式
  6. mybatis 批量更新 Parameter &#39;__frch_item_0&#39; not found. Available parameters are [list]
  7. git 回退各种场景操作
  8. 详解在Linux下实现(彩色)进度条程序,并通过makefile进行编译.
  9. Linux 保护文件 不给修改
  10. MVC 开发模式
  11. java中类的加载顺序介绍(ClassLoader)
  12. 【DevOps】为什么我们永远疲于奔命?
  13. Node.js Streams:你需要知道的一切
  14. kafka 官方示例代码--消费者
  15. CS小分队第一阶段冲刺站立会议(5月12日)
  16. 什么是阻塞式和非阻塞io流?
  17. jQuery find()方法 eq()方法
  18. 流畅的python和cookbook学习笔记(八)
  19. 1001 害死人不偿命的(3n+1)猜想 (15 分)
  20. [转载]Ubuntu 14.04中root 密码忘记解决方法

热门文章

  1. Unity3D for VR 学习(7): 360&#176;全景照片
  2. Linux内核设计第一周学习总结 计算机如何工作
  3. 把lighttpd配置为系统服务
  4. ER-18
  5. [POI2008]MAF-Mafia
  6. Linux基础-配置网络、集群内主机名设定、ssh登入、bash命令、通配符(元字符)
  7. mysql 给用户赋值权限
  8. MVC网站发布到 IIS
  9. Xamarin Error:Could not find android.jar for API Level 23.
  10. 2017 Multi-University Training Contest - Team 1