Django学习day15BBS项目开发3.0
每日测验
"""
今日考题
1.django admin作用及用法
2.media配置如何实现,基于该配置能够做到什么以及需要注意什么
3.阐述博客园为何支持用户自定义个人站点样式,内部可以如何实现
4.阐述侧边栏展示及筛选功能具体业务逻辑
"""
课程安排
"""
下周一再讲一天
"""
内容回顾
登陆功能后端实现
# 前后端基于ajax交互的话 那么后端通常会返回字典格式数据
"""
1.验证码判断是否正确
忽略大小写
"""
首页搭建
# django admin后台管理
"""
urls.py自带的那个url 特点:
能够自动生成注册了的模型表的增删改查四条url及相应的界面 使用
在对应的应用下的admin.py文件中注册模型表即可
admin.site.register(models.UserInfo)
...
class UserInfo(models.Model):
username = models.CharField(verbose_name='字段名')
class Meta:
verbose_name_plural = '表名' 针对bbs在绑定数据的时候一定要细心
1.先去文章表里面绑定数据
2.个人站点
3.文章分类
4.将用户和个人站点绑定关系
5.文章与文章标签 扩展:admin路由分发的本质
# 路由分发本质 include 可以无限制的嵌套N多层
url(r'^index/',([],None,None)) # url(r'^index/',([
# url(r'^index_1/',([
# url(r'^index_1_1',index),
# url(r'^index_1_2',index),
# url(r'^index_1_3',index),
# ],None,None)),
# url(r'^index_2/',index),
# url(r'^index_3/',index),
# ],None,None)),
"""
media配置
"""
网址所使用到的静态资源默认都是放在static文件夹下
用户上传的静态文件资源也应该单独找个位置存放 media配置
settings.py
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
用户上传文件会自动创建media文件夹然后在该文件夹内存储数据
"""
如何自定义暴露后端资源
# 你需要自己在urls.py中书写代码
from django.views.static import serve
from BBS14 import settings # 固定写法 不要自己改动
url(r'^media/(?P<path>.*)',serve,{'document_root':settings.MEDIA_ROOT}),
个人站点
# 由于url方法第一个参数是正则表达式,所以当路由特别多的时候,可能会出现被顶替的情况,针对这种情况有两种解决方式
1.修改正则表达式
2.调整url方法的位置 """
1.页面布局不再是282 变成左右布局
2.个人站点每个人的样式都不一样内部大致如何实现的
内部给每个人开设了可以自定义css和js的文件接口并且用户自定义之后会将用户的文件保存下来,之后在打开用户界面的时候会自动加载用户自己写的css和js从而实现每个用户界面不一样的情况
3.侧边栏展示问题
只要你的orm学的没有问题一般情况下不会有难度
只要是queryset对象就可以无限制的点击queryset对象方法
filter().filter().filter().filter() # 1 查询当前用户所有的分类及分类下的文章数
# 2 查询当前用户所有的标签及标签下的文章数
# 3 按照年月统计所有的文章
1.需要截取日期字段
参考官网提供的方法
from django.db.models.functions import TruncMonth
date_list = models.Article.objects.filter(blog=blog).annotate(month=TruncMonth('create_time')).values('month').annotate(count_num=Count('pk')).values_list('month','count_num') 2.如果按照上述写法出现报错,那么需要你去配置文件中修改时区
TIME_ZONE = 'Asia/Shanghai'
USE_TZ = False
4.侧边栏筛选功能
1.多个url公用一个视图函数
2.当多个url公用一个视图函数的时候 你应该思考着多个url能不能优化一下
# 个人站点页面搭建
url(r'^(?P<username>\w+)/$',views.site,name='site'),
# 侧边栏筛选功能
# url(r'^(?P<username>\w+)/category/(\d+)/',views.site),
# url(r'^(?P<username>\w+)/tag/(\d+)/',views.site),
# url(r'^(?P<username>\w+)/archive/(\w+)/',views.site),
# 上面的三条url其实可以合并成一条
url(r'^(?P<username>\w+)/(?P<condition>category|tag|archive)/(?P<param>.*)/',views.site) if kwargs:
# print(kwargs) # {'condition': 'tag', 'param': '1'}
condition = kwargs.get('condition')
param = kwargs.get('param')
# 判断用户到底想按照哪个条件筛选数据
if condition == 'category':
article_list = article_list.filter(category_id=param)
elif condition == 'tag':
article_list = article_list.filter(tags__id=param)
else:
year,month = param.split('-') # 2020-11 [2020,11]
article_list = article_list.filter(create_time__year=year,create_time__month=month) 5.手动补全侧边栏url即可
"""
今日内容概要
ps:今日内容比较繁琐(逻辑和代码量稍微多了一点),认真听~
- 侧边栏制作成inclusion_tag
- 文章的点赞点踩(重点)
- 文章的评论(重点)
- 先只做根评论
- 之后再做子评论
- 小bug完善
文章详情页
# url设计
/username/article/1
# 先验证url是否会被其他url顶替
# 文章详情页和个人站点基本一致 所以用模版继承
# 侧边栏的渲染需要传输数据才能渲染 并且该侧边栏在很多页面都需要使用
1.哪个地方用就拷贝需要的代码(不推荐 有点繁琐)
2.将侧边栏制作成inclusion_tag
"""
步骤
1.在应用下创建一个名字必须叫templatetags文件夹
2.在该文件夹内创建一个任意名称的py文件
3.在该py文件内先固定写两行代码
from django import template
register = template.Library()
# 自定义过滤器
# 自定义标签
# 自定义inclusion_tag
"""
# 自定义inclusion_tag
@register.inclusion_tag('left_menu.html')
def left_menu(username):
# 构造侧边栏需要的数据
user_obj = models.UserInfo.objects.filter(username=username).first()
blog = user_obj.blog
# 1 查询当前用户所有的分类及分类下的文章数
category_list = models.Category.objects.filter(blog=blog).annotate(count_num=Count('article__pk')).values_list(
'name', 'count_num', 'pk')
# print(category_list) # <QuerySet [('jason的分类一', 2), ('jason的分类二', 1), ('jason的分类三', 1)]>
# 2 查询当前用户所有的标签及标签下的文章数
tag_list = models.Tag.objects.filter(blog=blog).annotate(count_num=Count('article__pk')).values_list('name',
'count_num',
'pk')
# print(tag_list) # <QuerySet [('tank的标签一', 1), ('tank的标签二', 1), ('tank的标签三', 2)]>
# 3 按照年月统计所有的文章
date_list = models.Article.objects.filter(blog=blog).annotate(month=TruncMonth('create_time')).values(
'month').annotate(count_num=Count('pk')).values_list('month', 'count_num')
# print(date_list)
return locals()
文章点赞点踩
"""
浏览器上你看到的花里胡哨的页面,内部都是HTML(前端)代码
那现在我们的文章内容应该写什么??? >>> html代码
如何拷贝文章
copy outerhtml
1.拷贝文章
2.拷贝点赞点踩
1.拷贝前端点赞点踩图标 只拷了html
2.css也要拷贝
由于有图片防盗链的问题 所以将图片直接下载到本地
课下思考:
前端如何区分用户是点了赞还是点了踩
1.给标签各自绑定一个事件
两个标签对应的代码其实基本一样,仅仅是是否点赞点踩这一个参数不一样而已
2.二合一
给两个标签绑定一个事件
// 给所有的action类绑定事件
$('.action').click(function () {
alert($(this).hasClass('diggit'))
})
由于点赞点踩内部有一定的业务逻辑,所以后端单独开设视图函数处理
"""
# 个人建议:写代码先把所有正确的逻辑写完再去考虑错误的逻辑 不要试图两者兼得
import json
from django.db.models import F
def up_or_down(request):
"""
1.校验用户是否登陆
2.判断当前文章是否是当前用户自己写的(自己不能点自己的文章)
3.当前用户是否已经给当前文章点过了
4.操作数据库了
:param request:
:return:
"""
if request.is_ajax():
back_dic = {'code':1000,'msg':''}
# 1 先判断当前用户是否登陆
if request.user.is_authenticated():
article_id = request.POST.get('article_id')
is_up = request.POST.get('is_up')
# print(is_up,type(is_up)) # true <class 'str'>
is_up = json.loads(is_up) # 记得转换
# print(is_up, type(is_up)) # True <class 'bool'>
# 2 判断当前文章是否是当前用户自己写的 根据文章id查询文章对象 根据文章对象查作者 根request.user比对
article_obj = models.Article.objects.filter(pk=article_id).first()
if not article_obj.blog.userinfo == request.user:
# 3 校验当前用户是否已经点了 哪个地方记录了用户到底点没点
is_click = models.UpAndDown.objects.filter(user=request.user,article=article_obj)
if not is_click:
# 4 操作数据库 记录数据 要同步操作普通字段
# 判断当前用户点了赞还是踩 从而决定给哪个字段加一
if is_up:
# 给点赞数加一
models.Article.objects.filter(pk=article_id).update(up_num = F('up_num') + 1)
back_dic['msg'] = '点赞成功'
else:
# 给点踩数加一
models.Article.objects.filter(pk=article_id).update(down_num=F('down_num') + 1)
back_dic['msg'] = '点踩成功'
# 操作点赞点踩表
models.UpAndDown.objects.create(user=request.user,article=article_obj,is_up=is_up)
else:
back_dic['code'] = 1001
back_dic['msg'] = '你已经点过了,不能再点了' # 这里你可以做的更加的详细 提示用户到底点了赞还是点了踩
else:
back_dic['code'] = 1002
back_dic['msg'] = '你个臭不要脸的!'
else:
back_dic['code'] = 1003
back_dic['msg'] = '请先<a href="/login/">登陆</a>'
return JsonResponse(back_dic)
<script>
// 给所有的action类绑定事件
$('.action').click(function () {
{#alert($(this).hasClass('diggit'))#}
let isUp = $(this).hasClass('diggit');
let $div = $(this);
// 朝后端发送ajax请求
$.ajax({
url:'/up_or_down/',
type:'post',
data:{
'article_id':'{{ article_obj.pk }}',
'is_up':isUp,
'csrfmiddlewaretoken':'{{ csrf_token }}'
},
success:function (args) {
if(args.code == 1000){
$('#digg_tips').text(args.msg)
// 将前端的数字加一
// 先获取到之前的数字
let oldNum = $div.children().text(); // 文本 是字符类型
// 易错点
$div.children().text(Number(oldNum) + 1) // 字符串拼接了 1+1 = 11 11 + 1 = 111
}else{
$('#digg_tips').html(args.msg)
}
}
})
})
</script>
文章评论
"""
我们先写根评论
再写子评论
点击评论按钮需要将评论框里面的内容清空
根评论有两步渲染方式
1.DOM临时渲染
2.页面刷新render渲染
子评论
点击回复按钮发生了几件事
1.评论框自动聚焦
2.将回复按钮所在的那一行评论人的姓名
@username
3.评论框内部自动换行
根评论子评论都是点击一个按钮朝后端提交数据的
parent_id
根评论子评论区别在哪?
parent_id
"""
Django学习day15BBS项目开发3.0的更多相关文章
- Django学习day15BBS项目开发4.0(完结)
每日测验 """ 今日考题: 1.简述自定义标签,过滤器,inclusion_tag的方法,并简要说一说三者的特点及响应流程 2.简述个人侧边栏展示及筛选业务逻辑 3.简 ...
- Django学习day15BBS项目开发2.0
每日测验 """ 今日日考 1.img标签src属性可以指代的值有哪些,各有什么特点 2.pillow模块是干什么用的,主要的方法有哪些 3.简述登陆功能图片验证码相关逻 ...
- Django学习day14BBS项目开发1.0
每日测验 """ 1.简述auth模块功能 2.简述项目开发流程 3.简述bbs表设计 """ 内容回顾 auth模块 "&quo ...
- Django实际站点项目开发经验谈
开发了两个月的Django站点正式上线了,看着网站从无到有,从前端到后台,从本地开发到环境部署,一点一滴的堆砌成型,着实带给我不小的乐趣. Django站点介绍: 开发环境:阿里云服务器centos6 ...
- Anytime项目开发记录0
Anytime,中文名:我很忙. 开发者:孤独的猫咪神. 这个项目会持续更新,直到我决定不再维护这个APP. 2014年3月10日:近日有事,暂时断更.希望可以会尽快完事. 2014年3月27日:很抱 ...
- Django SNS 微博项目开发
1.功能需求 一个人可以follow很多人 一个用户如果发了新weibo会自动推送所有关注他的人 可以搜索.关注其它用户 可以分类关注 用户可以发weibo, 转发.收藏.@其它人 发微博时可选择公开 ...
- Django学习笔记 (一) 开发环境配置
Django是一个开放源代码的Web应用框架,由Python写成. 采用了MVC的软件设计模式,即模型M,视图V和控制器C. 1. Python安装 下载地址: http://www.python.o ...
- python学习之-项目开发目录规范
软件目录结构规范有什么好处: 通过规范化,能够更好的控制软件结构,让程序具有更高的可读性. 项目目录组织结构如下: Foo/ # 项目名 --bin/ # 可执行文件目录 --foo # 可执行程序 ...
- Django学习之项目结构优化
其实就是采用包结构,比如: 目录models,包含__init__.py,a.py,b.py 然后将model class写在a和b中,但是这样的话,导入时就要改变了! from models imp ...
随机推荐
- FreeRTOS-05-队列
说明 本文仅作为学习FreeRTOS的记录文档,作为初学者肯定很多理解不对甚至错误的地方,望网友指正. FreeRTOS是一个RTOS(实时操作系统)系统,支持抢占式.合作式和时间片调度.适用于微处理 ...
- thunderbird发送纯文本邮件
向邮件列表中发邮件时,要求邮件格式必须是纯文本格式的,在thunderbird中,邮件格式(plain text或者html格式)在[工具->账户设置->[账户名称]->通讯录]下的 ...
- NOIP 模拟 6 辣鸡
题解 难得啊,本来能 \(AC\) 的一道题,注释没删,挂了五分,难受 此题暴力很好想,就是直接 \(n^2\) 枚举不同的矩阵组合,记录块内答案和跨块的答案 出题人不会告诉你,这题只要输出块内答案就 ...
- SpringCloud War 包部署导致服务未正常注册到 Nacos 问题
转载地址:https://blog.csdn.net/qq_28379809/article/details/103773149
- .NET Core程序发布报错:project.assets.json”没有“.NETCoreApp,Version=v3.1/win-x64”的目标。确保已运行还原,且“netcoreapp3.1”已包含在项目的 TargetFrameworks中。
在控制台中使用命令发布.NET Core程序的时候,报如下的错误: project.assets.json"没有".NETCoreApp,Version=v3.1/win-x64& ...
- Qt MDI及其使用方法(详解版)
统的应用程序设计中有多文档界面(Multi-document Interface,MDI)应用程序,Qt 为设计 MDI 应用程序提供了支持. 本节的实例 samp6_4 是一个 MDI 应用程序,程 ...
- 聊聊 PC 端自动化最佳方案 - Pywinauto
1. 前言 大家好,我是安果! 上一篇文章,聊到 PC 端的一种自动化方案:WinAppDriver 聊聊 PC 端自动化最佳方案 - WinAppDriver 有小伙伴后台给我留言,说「 pywin ...
- Kickstart部署之FTP架构
原文转自:https://www.cnblogs.com/itzgr/p/10029551.html作者:木二 目录 一 准备 1.1 完整架构:Kickstart+DHCP+VSFTP+TFTP+P ...
- Python安装环境配置和多版本共存
Python安装环境配置和多版本共存 1.环境变量配置: (1) 右键点击"计算机",然后点击"属性" (2) 然后点击"高级系统设置" ( ...
- go语言文件系统
检测文件是否存在 //存在返回 true,不存在返回 false func fileIfExist(filename string) bool { _, err := os.Stat(filename ...