一、回顾 

    1. BBS项目 CMS
1. 登录
1. form组件
2. auth模块
3. 验证码
2. 注册
1. form组件
1. 生成html代码
直接for循环form_obj,就能够遍历所有字段
2. 验证
1. 默认的那些验证
2. 正则的验证
3. 全局钩子做确认密码的验证
4. 判断用户名是否已经存在
1. input框失去焦点就发ajax到后端判断
2. form组件中使用局部钩子来判断 2. auth模块 --> 扩展auth_user表 --> create_user()
1. UserInfo这个类里面,avatar是一个FileField
avatar = models.FileField(upload_to="avatars/", default="avatars/default.png")
2. 注意事项:
1. FileField保存的是一个路径,而不是一个文件
2. upload_to:具体保存的文件路径就会在media目录下
3. 上传头像
1. ajax如何上传文件
2. Django中media的配置
1. settings.py中:
- MEDIA_URL:别名
- MEDIA_ROOT:给用户上传的所有文件指定一个存放目录
2. urls.py中:
from django.views.static import serve
from django.conf import settings url(r'^media/(?P<path>.*)', serve, {"document_root": settings.MEDIA_ROOT})
3. 博客首页
1. 文章列表(排样式)
2. 分页
1. 封装的要彻底
2. 封装后的结果要有普适性(url要写成配置项)
4. 个人博客主页
1. 分类
1. 文章分类
2. 文章标签
2. 日期归档
1. 日期格式化函数 --> MySQL内置的函数都有哪一些? --> 《漫画数据库》
1. MySQL:DATE_FORMAT('字段', '格式')
2. sqlite:strftime('格式', '字段') 2. ORM中如何执行原生的SQL语句
1. 使用extra()在执行ORM查询的同时,嵌入一些SQL语句
2. 直接执行原生SQL语句
from django.db import connection
cursor = connection.cursor()
cursor.execute('select id from userinfo;')
cursor.fetchall()
3. 分组聚合
QuertySet.annotate() --> 分组,前面查的是什么字段就按什么字段分组
QuertySet.aggregate() --> 聚合,给QuerySet中的每个对象多一个属性 4. 4合1路由
不同的路由可以使用同一个视图函数!!! --> 视图函数中通过参数的不同,实现不同的功能
5. 文章详情页
1. 母板继承
2. inclusion_tag
1. 返回一段HTML代码,用数据填充的HTML代码
2. 具体的写法
1. 在app下面创建一个名为 templatetags 的 Python Package
2. 在上面的包中创建一个 py文件
3. 按照inclusion_tag的格式要求写功能函数 from django import template
register = template.Library() @register.inclusion_tag(file='xx.html')
def show_menu(*arg):
...
return {"k1": "v1"}
(xx.html中使用k1这个变量)
3. 点赞
1. ajax发送点赞的请求
1. 点赞必须是登录用户,没登录跳转到登录页面
2. 不能给自己的文章点赞
3. 一个用户只能给一篇文章点一次赞或踩一次 2. 后端创建点赞记录(事务操作)
1. 创建新的点赞记录
2. 去对应的文章表里把点赞数更新一个
3. ORM事务操作
from django.db import transaction with transaction.atomic():
sql1;
sql2; 4. Django模板语言里面的JS代码
如何在js中引用模板语言的变量,注意加引号!!!

bss项目回顾

二、今日内容(评论楼和评论树)

1.评论展示HTML:注意给每个评论楼层添加一个comment_id,后续别人回复改评论,取其值为父评论id

    <!-- 评论展示部分 开始-->
<div class="list-group commnet_list">
{% for comment in comment_list %} <a href="javascript:void(0);" class="list-group-item">
<h4 class="list-group-item-heading" pid='{{ comment.id }}'>
<span>{{ forloop.counter }}楼</span>
<span>{{ comment.create_time|date:'Y-m-d H:i:s' }}</span>
<span>{{ comment.user.username }}</span>
<span class="pull-right reply">回复</span>
</h4>
{% if comment.parent_comment %}
<span style="display: block;color: blue">@{{ comment.parent_comment.user.username }}</span>
{% endif %}
<p class="list-group-item-text" style="text-indent:20px; ">{{ comment.content }}</p>
</a>
{% endfor %}
</div>
<!-- 评论展示部分 结束-->

评论展示HTML

2.设置事件委托,点击回复定位至评论框,并在评论框内设置出现@用户名,存储comment_id 至button标签

        $('.list-group').on('click', '.reply', function () {
var replyName = $(this).prev().text();
$('#new-comment').focus().val('@' + replyName + '\n');
var pId = $(this).parent().attr('pid');
$('#submit').data('pId', pId);
})

存父评论pid等

3.评论区书写代码

    <!-- 评论书写部分 开始-->
<hr>
<h4>发表评论</h4>
<hr>
<div>
<span>用户名:</span>
<input type="text" value="{{ request.user.username }}" disabled>
</div>
<div>
<p>评论:</p>
<textarea name="comment" id="new-comment" cols="60" rows="10"></textarea>
</div>
<div>
<button class="btn" id="submit">提交</button>
</div>
<div style="width: 100%;height: 100px;"></div> <!-- 评论书写部分 结束-->

评论区HTML代码

4.ajax提交内容,通过button标签中存储的pid是否存在判断是子评论还是一级评论并处理评论内容(去除@XXX),ajax提交并返回响应数据,js添加响应html代码至浏览器。

$('#submit').click(function () {
var content = $('#new-comment').val();
var articleId = '{{ article.id }}';
var parentId = $('#submit').data('pId') || "";
if (parentId) {
content = content.slice(content.indexOf('\n') + 1,)
}
$.ajax({
url: '/comment/?next=' + '{{ request.get_full_path }}',
type: 'post',
data: {
content: content,
article_id: articleId,
parent_id: parentId,
csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
},
success: function (res) {
if (res.code === 0) {
var count = $('.commnet_list>a').length+1;
{#判断是否需要@回复,还是一级评论#}
if (res.data.parentName) {
var reply_html = `<span style="display: block;color: blue">@${res.data.parentName }</span>`;
} else {
var reply_html = ''
}
var comment_html = `
<a href="javascript:void(0);" class="list-group-item">
<h4 class="list-group-item-heading" pid='${ res.data.commentId }'>
<span>${ count }楼</span>
<span>${ res.data.create_time}</span>
<span>${ res.data.username }</span>
<span class="pull-right reply">回复</span>
</h4>`+reply_html+
`<p class="list-group-item-text" style="text-indent:20px; ">${ res.data.content }</p> </a>`
$('.commnet_list').append(comment_html);
$('#new-comment').val('');
$('#submit').removeData('pId')
}
}
}) }) </script> <script>
var userId = '{{ request.user.pk }}';
var articleId = '{{ article.id }}';
var isUp = false;
$(".digg").click(function () {
var username = '{{ username }}'
var loginname = '{{ request.user.username }}'
if (!'{{ request.user.username }}') {
{#如果用户未登录,跳转到登录页面#}
location.href = '/login2/?next=' + '{{ request.get_full_path }}';
}
{#如果用户给自己点赞或反对,不行#}
else if (username == loginname) {
if ($(this).hasClass('diggit')) {
$('#msg').text('不能给自己点赞!').css('color', 'red');
} else {
$('#msg').text('不能反对自己!').css('color', 'red');
}
}
else {
if ($(this).hasClass('diggit')) {
isUp = true;
}
$.ajax({
url: '/evalute/',
type: 'post',
data: {
csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
userId: userId,
articleId: articleId,
isUp: isUp,
},
success: function (res) {
if (res.code !== 0) {
$('#msg').text(res.msg).css('color', 'red');
} else { if (isUp) {
var $up = $('#digg_count')
$up.text(+$up.text() + 1)
} else {
var $down = $('#bury_count')
$down.text(+$down.text() + 1) }
} }
})
}
})
{#用户对已点赞或踩灭的文章进行取消!显示#}
$('document').ready(function () {
$.ajax({
url: '/cancel/',
type: 'post',
data: {
userId: '{{ request.user.id }}',
articleId: '{{ article.id }}',
csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
},
success: function (res) {
if (res.code === 0) {
if (res.msg === 1) {
$('#digg_tips').html('您已推荐过,<a href="javascript:void(0);" class="digg_gray">取消 </a>');
}
else {
$('#digg_tips').html('您已反对过,<a href="javascript:void(0);" class="digg_gray">取消 </a>');
}
} else {
$('#digg_tips').css('display', 'none');
}
}
})
}) $('#digg_tips').click(function () {
$.ajax({
url: '/cancel1/',
type: 'post',
data: {
userId: '{{ request.user.id }}',
articleId: '{{ article.id }}',
csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val()
},
success: function (res) {
if (res.code !== 0) {
$('#digg_tips').html('推荐取消失败,<a href="javascript:void(0);" class="digg_gray">刷新重试</a>');
} else {
location.reload();
}
}
})
})

三、预习和扩展

1.模板中表单的简单写法

2.注册过程中检验是否存在同名用户的局部钩子

3.DOM元素存储data、获取data、删除data

4.JS三元运算和 ||

5.JS字符串截取

6.事件委托的运用

7. js字符串前加+号可以将字符串变成数字:

$down.text(+$down.text() + 1)

python全栈开发day78、79 --bss项目的更多相关文章

  1. Python全栈开发【面向对象进阶】

    Python全栈开发[面向对象进阶] 本节内容: isinstance(obj,cls)和issubclass(sub,super) 反射 __setattr__,__delattr__,__geta ...

  2. Python全栈开发【面向对象】

    Python全栈开发[面向对象] 本节内容: 三大编程范式 面向对象设计与面向对象编程 类和对象 静态属性.类方法.静态方法 类组合 继承 多态 封装 三大编程范式 三大编程范式: 1.面向过程编程 ...

  3. Win10构建Python全栈开发环境With WSL

    目录 Win10构建Python全栈开发环境With WSL 启动WSL 总结 对<Dev on Windows with WSL>的补充 Win10构建Python全栈开发环境With ...

  4. python 全栈开发,Day99(作业讲解,DRF版本,DRF分页,DRF序列化进阶)

    昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确. - API (IOS,安卓,PC,微信小程序...) - vue.js等框架编写前端时,会比之前写jQuery ...

  5. Python 全栈开发【第0篇】:目录

    Python 全栈开发[第0篇]:目录   第一阶段:Python 开发入门 Python 全栈开发[第一篇]:计算机原理&Linux系统入门 Python 全栈开发[第二篇]:Python基 ...

  6. Python全栈开发【模块】

    Python全栈开发[模块] 本节内容: 模块介绍 time random os sys json & picle shelve XML hashlib ConfigParser loggin ...

  7. Python全栈开发【基础四】

    Python全栈开发[基础四] 本节内容: 匿名函数(lambda) 函数式编程(map,filter,reduce) 文件处理 迭代器 三元表达式 列表解析与生成器表达式 生成器 匿名函数 lamb ...

  8. Python全栈开发【基础三】

    Python全栈开发[基础三]  本节内容: 函数(全局与局部变量) 递归 内置函数 函数 一.定义和使用 函数最重要的是减少代码的重用性和增强代码可读性 def 函数名(参数): ... 函数体 . ...

  9. Python全栈开发【基础二】

    Python全栈开发[基础二] 本节内容: Python 运算符(算术运算.比较运算.赋值运算.逻辑运算.成员运算) 基本数据类型(数字.布尔值.字符串.列表.元组.字典) 其他(编码,range,f ...

随机推荐

  1. hibernate框架学习第一天:hibernate介绍及基本操作

    框架辅助开发者进行开发,半成品软件,开发者与框架进行合作开发 Hibernate3Hibernate是一种基于Java的轻量级的ORM框架 基于Java:底层实现是Java语言,可以脱离WEB,在纯J ...

  2. T-SQL ORDER BY子句 排序方式

    MS SQL Server ORDER BY子句用于根据一个或多个列以升序或降序对数据进行排序. 默认情况下,一些数据库排序查询结果按升序排列. 语法 以下是ORDER BY子句的基本语法. SELE ...

  3. NodeJS+Express+MySQL开发小记(2):服务器部署

    http://borninsummer.com/2015/06/17/notes-on-developing-nodejs-webapp/ NodeJS+Express+MySQL开发小记(1)里讲过 ...

  4. ASP.NET MVC5高级编程 之 模型

    1. 为MVC Music Store建模 Models文件夹(右击) --> 添加 --> 类 为类添加对应的属性: public class Album { public virtua ...

  5. Ex 7_17 考虑如下的网络(其中数字为对应边的容量)...第十三次作业

    (a) 利用ford-fulkerson算法即可求出最大流和最小分割. (b) 剩余网络为 由S可达的顶点为A.B.可达T的顶点为C. (c) 瓶颈边有e(A,C),e(B,C). (d) 下图中不包 ...

  6. 8大排序之Python实现 冒泡排序优化

    1.冒泡排序(从大到小):交换发生在内部循环 稳定的排序 冒泡排序的平均时间复杂度是O(n2),最好的时间复杂度是O(n),最坏的时间复杂度是O(n2),空间复杂度为O(1) 冒泡排序的优化在于did ...

  7. Java、Apache Tomcat下载与安装及环境变量配置

    1.Java JDK 与 Apache Tomcat 下载 JDK 下载 Apache Tomcat 下载 2.安装与环境变量配置 关于 JDK 的安装挺简单的,网上教程也挺多,Tomcat 下载免安 ...

  8. Mysql8.0安装步骤

    Mysql8.0安装步骤 2018年05月10日 14:39:05 93年的香槟 阅读数:19628 标签: mysql 更多 个人分类: 数据库   版权声明:本文为博主原创文章,未经博主允许不得转 ...

  9. Java 的 Api 文档生成工具 JApiDocs 程序文档工具

    JApiDocs 详细介绍 简介 JApiDocs 是一个符合 Java 编程习惯的 Api 文档生成工具.最大程度地利用 Java 的语法特性,你只管用心设计好接口,添加必要的注释,JApiDocs ...

  10. Remove Duplicates from Sorted ListII

    给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字. 示例 1: 输入: 1->2->3->3->4->4->5 输出: 1-&g ...