每日测验

  1. """
  2. 今日考题
  3. 1.django admin作用及用法
  4. 2.media配置如何实现,基于该配置能够做到什么以及需要注意什么
  5. 3.阐述博客园为何支持用户自定义个人站点样式,内部可以如何实现
  6. 4.阐述侧边栏展示及筛选功能具体业务逻辑
  7. """

课程安排

  1. """
  2. 下周一再讲一天
  3. """

内容回顾

  • 登陆功能后端实现

    1. # 前后端基于ajax交互的话 那么后端通常会返回字典格式数据
    2. """
    3. 1.验证码判断是否正确
    4. 忽略大小写
    5. """
  • 首页搭建

    1. # django admin后台管理
    2. """
    3. urls.py自带的那个url
    4. 特点:
    5. 能够自动生成注册了的模型表的增删改查四条url及相应的界面
    6. 使用
    7. 在对应的应用下的admin.py文件中注册模型表即可
    8. admin.site.register(models.UserInfo)
    9. ...
    10. class UserInfo(models.Model):
    11. username = models.CharField(verbose_name='字段名')
    12. class Meta:
    13. verbose_name_plural = '表名'
    14. 针对bbs在绑定数据的时候一定要细心
    15. 1.先去文章表里面绑定数据
    16. 2.个人站点
    17. 3.文章分类
    18. 4.将用户和个人站点绑定关系
    19. 5.文章与文章标签
    20. 扩展:admin路由分发的本质
    21. # 路由分发本质 include 可以无限制的嵌套N多层
    22. url(r'^index/',([],None,None))
    23. # url(r'^index/',([
    24. # url(r'^index_1/',([
    25. # url(r'^index_1_1',index),
    26. # url(r'^index_1_2',index),
    27. # url(r'^index_1_3',index),
    28. # ],None,None)),
    29. # url(r'^index_2/',index),
    30. # url(r'^index_3/',index),
    31. # ],None,None)),
    32. """
  • media配置

    1. """
    2. 网址所使用到的静态资源默认都是放在static文件夹下
    3. 用户上传的静态文件资源也应该单独找个位置存放
    4. media配置
    5. settings.py
    6. MEDIA_ROOT = os.path.join(BASE_DIR,'media')
    7. 用户上传文件会自动创建media文件夹然后在该文件夹内存储数据
    8. """
  • 如何自定义暴露后端资源

    1. # 你需要自己在urls.py中书写代码
    2. from django.views.static import serve
    3. from BBS14 import settings
    4. # 固定写法 不要自己改动
    5. url(r'^media/(?P<path>.*)',serve,{'document_root':settings.MEDIA_ROOT}),
  • 个人站点

    1. # 由于url方法第一个参数是正则表达式,所以当路由特别多的时候,可能会出现被顶替的情况,针对这种情况有两种解决方式
    2. 1.修改正则表达式
    3. 2.调整url方法的位置
    4. """
    5. 1.页面布局不再是282 变成左右布局
    6. 2.个人站点每个人的样式都不一样内部大致如何实现的
    7. 内部给每个人开设了可以自定义css和js的文件接口并且用户自定义之后会将用户的文件保存下来,之后在打开用户界面的时候会自动加载用户自己写的css和js从而实现每个用户界面不一样的情况
    8. 3.侧边栏展示问题
    9. 只要你的orm学的没有问题一般情况下不会有难度
    10. 只要是queryset对象就可以无限制的点击queryset对象方法
    11. filter().filter().filter().filter()
    12. # 1 查询当前用户所有的分类及分类下的文章数
    13. # 2 查询当前用户所有的标签及标签下的文章数
    14. # 3 按照年月统计所有的文章
    15. 1.需要截取日期字段
    16. 参考官网提供的方法
    17. from django.db.models.functions import TruncMonth
    18. 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')
    19. 2.如果按照上述写法出现报错,那么需要你去配置文件中修改时区
    20. TIME_ZONE = 'Asia/Shanghai'
    21. USE_TZ = False
    22. 4.侧边栏筛选功能
    23. 1.多个url公用一个视图函数
    24. 2.当多个url公用一个视图函数的时候 你应该思考着多个url能不能优化一下
    25. # 个人站点页面搭建
    26. url(r'^(?P<username>\w+)/$',views.site,name='site'),
    27. # 侧边栏筛选功能
    28. # url(r'^(?P<username>\w+)/category/(\d+)/',views.site),
    29. # url(r'^(?P<username>\w+)/tag/(\d+)/',views.site),
    30. # url(r'^(?P<username>\w+)/archive/(\w+)/',views.site),
    31. # 上面的三条url其实可以合并成一条
    32. url(r'^(?P<username>\w+)/(?P<condition>category|tag|archive)/(?P<param>.*)/',views.site)
    33. if kwargs:
    34. # print(kwargs) # {'condition': 'tag', 'param': '1'}
    35. condition = kwargs.get('condition')
    36. param = kwargs.get('param')
    37. # 判断用户到底想按照哪个条件筛选数据
    38. if condition == 'category':
    39. article_list = article_list.filter(category_id=param)
    40. elif condition == 'tag':
    41. article_list = article_list.filter(tags__id=param)
    42. else:
    43. year,month = param.split('-') # 2020-11 [2020,11]
    44. article_list = article_list.filter(create_time__year=year,create_time__month=month)
    45. 5.手动补全侧边栏url即可
    46. """

今日内容概要

ps:今日内容比较繁琐(逻辑和代码量稍微多了一点),认真听~

  • 侧边栏制作成inclusion_tag
  • 文章的点赞点踩(重点)
  • 文章的评论(重点)
    • 先只做根评论
    • 之后再做子评论
    • 小bug完善

文章详情页

  1. # url设计
  2. /username/article/1
  3. # 先验证url是否会被其他url顶替
  4. # 文章详情页和个人站点基本一致 所以用模版继承
  5. # 侧边栏的渲染需要传输数据才能渲染 并且该侧边栏在很多页面都需要使用
  6. 1.哪个地方用就拷贝需要的代码(不推荐 有点繁琐)
  7. 2.将侧边栏制作成inclusion_tag
  8. """
  9. 步骤
  10. 1.在应用下创建一个名字必须叫templatetags文件夹
  11. 2.在该文件夹内创建一个任意名称的py文件
  12. 3.在该py文件内先固定写两行代码
  13. from django import template
  14. register = template.Library()
  15. # 自定义过滤器
  16. # 自定义标签
  17. # 自定义inclusion_tag
  18. """
  19. # 自定义inclusion_tag
  20. @register.inclusion_tag('left_menu.html')
  21. def left_menu(username):
  22. # 构造侧边栏需要的数据
  23. user_obj = models.UserInfo.objects.filter(username=username).first()
  24. blog = user_obj.blog
  25. # 1 查询当前用户所有的分类及分类下的文章数
  26. category_list = models.Category.objects.filter(blog=blog).annotate(count_num=Count('article__pk')).values_list(
  27. 'name', 'count_num', 'pk')
  28. # print(category_list) # <QuerySet [('jason的分类一', 2), ('jason的分类二', 1), ('jason的分类三', 1)]>
  29. # 2 查询当前用户所有的标签及标签下的文章数
  30. tag_list = models.Tag.objects.filter(blog=blog).annotate(count_num=Count('article__pk')).values_list('name',
  31. 'count_num',
  32. 'pk')
  33. # print(tag_list) # <QuerySet [('tank的标签一', 1), ('tank的标签二', 1), ('tank的标签三', 2)]>
  34. # 3 按照年月统计所有的文章
  35. date_list = models.Article.objects.filter(blog=blog).annotate(month=TruncMonth('create_time')).values(
  36. 'month').annotate(count_num=Count('pk')).values_list('month', 'count_num')
  37. # print(date_list)
  38. return locals()

文章点赞点踩

  1. """
  2. 浏览器上你看到的花里胡哨的页面,内部都是HTML(前端)代码
  3. 那现在我们的文章内容应该写什么??? >>> html代码
  4. 如何拷贝文章
  5. copy outerhtml
  6. 1.拷贝文章
  7. 2.拷贝点赞点踩
  8. 1.拷贝前端点赞点踩图标 只拷了html
  9. 2.css也要拷贝
  10. 由于有图片防盗链的问题 所以将图片直接下载到本地
  11. 课下思考:
  12. 前端如何区分用户是点了赞还是点了踩
  13. 1.给标签各自绑定一个事件
  14. 两个标签对应的代码其实基本一样,仅仅是是否点赞点踩这一个参数不一样而已
  15. 2.二合一
  16. 给两个标签绑定一个事件
  17. // 给所有的action类绑定事件
  18. $('.action').click(function () {
  19. alert($(this).hasClass('diggit'))
  20. })
  21. 由于点赞点踩内部有一定的业务逻辑,所以后端单独开设视图函数处理
  22. """
  23. # 个人建议:写代码先把所有正确的逻辑写完再去考虑错误的逻辑 不要试图两者兼得
  24. import json
  25. from django.db.models import F
  26. def up_or_down(request):
  27. """
  28. 1.校验用户是否登陆
  29. 2.判断当前文章是否是当前用户自己写的(自己不能点自己的文章)
  30. 3.当前用户是否已经给当前文章点过了
  31. 4.操作数据库了
  32. :param request:
  33. :return:
  34. """
  35. if request.is_ajax():
  36. back_dic = {'code':1000,'msg':''}
  37. # 1 先判断当前用户是否登陆
  38. if request.user.is_authenticated():
  39. article_id = request.POST.get('article_id')
  40. is_up = request.POST.get('is_up')
  41. # print(is_up,type(is_up)) # true <class 'str'>
  42. is_up = json.loads(is_up) # 记得转换
  43. # print(is_up, type(is_up)) # True <class 'bool'>
  44. # 2 判断当前文章是否是当前用户自己写的 根据文章id查询文章对象 根据文章对象查作者 根request.user比对
  45. article_obj = models.Article.objects.filter(pk=article_id).first()
  46. if not article_obj.blog.userinfo == request.user:
  47. # 3 校验当前用户是否已经点了 哪个地方记录了用户到底点没点
  48. is_click = models.UpAndDown.objects.filter(user=request.user,article=article_obj)
  49. if not is_click:
  50. # 4 操作数据库 记录数据 要同步操作普通字段
  51. # 判断当前用户点了赞还是踩 从而决定给哪个字段加一
  52. if is_up:
  53. # 给点赞数加一
  54. models.Article.objects.filter(pk=article_id).update(up_num = F('up_num') + 1)
  55. back_dic['msg'] = '点赞成功'
  56. else:
  57. # 给点踩数加一
  58. models.Article.objects.filter(pk=article_id).update(down_num=F('down_num') + 1)
  59. back_dic['msg'] = '点踩成功'
  60. # 操作点赞点踩表
  61. models.UpAndDown.objects.create(user=request.user,article=article_obj,is_up=is_up)
  62. else:
  63. back_dic['code'] = 1001
  64. back_dic['msg'] = '你已经点过了,不能再点了' # 这里你可以做的更加的详细 提示用户到底点了赞还是点了踩
  65. else:
  66. back_dic['code'] = 1002
  67. back_dic['msg'] = '你个臭不要脸的!'
  68. else:
  69. back_dic['code'] = 1003
  70. back_dic['msg'] = '请先<a href="/login/">登陆</a>'
  71. return JsonResponse(back_dic)
  72. <script>
  73. // 给所有的action类绑定事件
  74. $('.action').click(function () {
  75. {#alert($(this).hasClass('diggit'))#}
  76. let isUp = $(this).hasClass('diggit');
  77. let $div = $(this);
  78. // 朝后端发送ajax请求
  79. $.ajax({
  80. url:'/up_or_down/',
  81. type:'post',
  82. data:{
  83. 'article_id':'{{ article_obj.pk }}',
  84. 'is_up':isUp,
  85. 'csrfmiddlewaretoken':'{{ csrf_token }}'
  86. },
  87. success:function (args) {
  88. if(args.code == 1000){
  89. $('#digg_tips').text(args.msg)
  90. // 将前端的数字加一
  91. // 先获取到之前的数字
  92. let oldNum = $div.children().text(); // 文本 是字符类型
  93. // 易错点
  94. $div.children().text(Number(oldNum) + 1) // 字符串拼接了 1+1 = 11 11 + 1 = 111
  95. }else{
  96. $('#digg_tips').html(args.msg)
  97. }
  98. }
  99. })
  100. })
  101. </script>

文章评论

  1. """
  2. 我们先写根评论
  3. 再写子评论
  4. 点击评论按钮需要将评论框里面的内容清空
  5. 根评论有两步渲染方式
  6. 1.DOM临时渲染
  7. 2.页面刷新render渲染
  8. 子评论
  9. 点击回复按钮发生了几件事
  10. 1.评论框自动聚焦
  11. 2.将回复按钮所在的那一行评论人的姓名
  12. @username
  13. 3.评论框内部自动换行
  14. 根评论子评论都是点击一个按钮朝后端提交数据的
  15. parent_id
  16. 根评论子评论区别在哪?
  17. parent_id
  18. """

Django学习day15BBS项目开发3.0的更多相关文章

  1. Django学习day15BBS项目开发4.0(完结)

    每日测验 """ 今日考题: 1.简述自定义标签,过滤器,inclusion_tag的方法,并简要说一说三者的特点及响应流程 2.简述个人侧边栏展示及筛选业务逻辑 3.简 ...

  2. Django学习day15BBS项目开发2.0

    每日测验 """ 今日日考 1.img标签src属性可以指代的值有哪些,各有什么特点 2.pillow模块是干什么用的,主要的方法有哪些 3.简述登陆功能图片验证码相关逻 ...

  3. Django学习day14BBS项目开发1.0

    每日测验 """ 1.简述auth模块功能 2.简述项目开发流程 3.简述bbs表设计 """ 内容回顾 auth模块 "&quo ...

  4. Django实际站点项目开发经验谈

    开发了两个月的Django站点正式上线了,看着网站从无到有,从前端到后台,从本地开发到环境部署,一点一滴的堆砌成型,着实带给我不小的乐趣. Django站点介绍: 开发环境:阿里云服务器centos6 ...

  5. Anytime项目开发记录0

    Anytime,中文名:我很忙. 开发者:孤独的猫咪神. 这个项目会持续更新,直到我决定不再维护这个APP. 2014年3月10日:近日有事,暂时断更.希望可以会尽快完事. 2014年3月27日:很抱 ...

  6. Django SNS 微博项目开发

    1.功能需求 一个人可以follow很多人 一个用户如果发了新weibo会自动推送所有关注他的人 可以搜索.关注其它用户 可以分类关注 用户可以发weibo, 转发.收藏.@其它人 发微博时可选择公开 ...

  7. Django学习笔记 (一) 开发环境配置

    Django是一个开放源代码的Web应用框架,由Python写成. 采用了MVC的软件设计模式,即模型M,视图V和控制器C. 1. Python安装 下载地址: http://www.python.o ...

  8. python学习之-项目开发目录规范

    软件目录结构规范有什么好处: 通过规范化,能够更好的控制软件结构,让程序具有更高的可读性. 项目目录组织结构如下: Foo/ # 项目名 --bin/ # 可执行文件目录 --foo # 可执行程序 ...

  9. Django学习之项目结构优化

    其实就是采用包结构,比如: 目录models,包含__init__.py,a.py,b.py 然后将model class写在a和b中,但是这样的话,导入时就要改变了! from models imp ...

随机推荐

  1. php本地文件包含 Writeup

    目录 本地文件包含 LFI本地文件包含案例一 LFI本地文件包含案例二 本地文件包含简介 文件包含函数加载的参数没有经过过滤或者严格的定义,可以被用户控制,包含其他恶意文件,导致了执行了非预期的代码. ...

  2. STM32—驱动DHT11数字温湿度传感器

    文章目录 DHT11模块简介 DHT11数据传输 DHT11通信时序 代码实现 相关引脚初始化 复位模块 判断响应模块 读取数据包模块 DHT11模块简介 DHT11数字温湿度传感器,用来测量环境的温 ...

  3. Django ORM多表查询

    基于双下划线查询 根据存的时候,字段的数据格式衍生的查询方法 1.年龄大于35岁 res = models.AuthorDetails.objects.filter(age__lt=80) print ...

  4. Synchronized和ReentranLock的区别

    1.底层实现上来说? Synchronized是JVM层面的锁,是Java关键字,通过monitor对象来完成. ReentranLock是API层面的锁底层使用AQS. 2.是否可手动释放锁? sy ...

  5. C++_COM 入门

    COM即组件对象模型(Component Object Model)是一种跨应用和语言共享二进制代码的方法.COM明确指出二进制模块(DLLS和EXES)必须被编译成与指定的结构匹配,其定义的二进制标 ...

  6. Vue2.0 axios 读取本地json文件

    参考:https://www.cnblogs.com/wdxue/p/8868982.html 1.下载插件 npm install axios --save 2.在main.js下引用axios i ...

  7. 十八:使用JDBC进行批处理

    一.使用Statement完成批处理 1.使用Statement对象添加要批量执行SQL语句,如下: 1 Statement.addBatch(sql1); 2 Statement.addBatch( ...

  8. 轻松入门vue系列

    一.vue基础语法 二.vue组件化开发 三.Vue前后端交互 四.vue前端路由 喜欢不要忘了点个赞哟

  9. 使用servlet中是否需要考虑线程问题

    package day09; import java.io.IOException; import javax.servlet.ServletException; import javax.servl ...

  10. Python的GPU编程实例——近邻表计算

    技术背景 GPU加速是现代工业各种场景中非常常用的一种技术,这得益于GPU计算的高度并行化.在Python中存在有多种GPU并行优化的解决方案,包括之前的博客中提到的cupy.pycuda和numba ...