blog项目知识点梳理
- 1.获取图片验证码:
- def get_validCode_img(request):
- # 方式1:
- # import os
- # path= os.path.join(settings.BASE_DIR,"blog","static","img","egon.jpg")
- #
- # with open(path,"rb") as f:
- # data=f.read()
- # 方式2:
- # from PIL import Image
- #
- # img=Image.new(mode="RGB",size=(120,40),color="green")
- #
- # f=open("validCode.png","wb")
- # img.save(f,"png")
- #
- # with open("validCode.png","rb") as f:
- # data=f.read()
- # 方式3:
- # from io import BytesIO
- #
- # from PIL import Image
- # img = Image.new(mode="RGB", size=(120, 40), color="blue")
- # f=BytesIO()
- # img.save(f,"png")
- # data=f.getvalue()
- # return HttpResponse(data)
- # 方式4 :
- from io import BytesIO
- import random
- from PIL import Image,ImageDraw,ImageFont
- img = Image.new(mode="RGB", size=(120, 40), color=(random.randint(0,255),random.randint(0,255),random.randint(0,255)))
- draw=ImageDraw.Draw(img,"RGB")
- font=ImageFont.truetype("blog/static/font/kumo.ttf",25)
- valid_list=[]
- for i in range(5):
- random_num=str(random.randint(0,9))
- random_lower_zimu=chr(random.randint(65,90))
- random_upper_zimu=chr(random.randint(97,122))
- random_char=random.choice([random_num,random_lower_zimu,random_upper_zimu])
- draw.text([5+i*24,10],random_char,(random.randint(0,255),random.randint(0,255),random.randint(0,255)),font=font)
- valid_list.append(random_char)
- f=BytesIO()
- img.save(f,"png")
- data=f.getvalue()
- valid_str="".join(valid_list)
- # print(valid_str)
- request.session["keepValidCode"]=valid_str
- return HttpResponse(data)
- 2.点击验证码图片刷新效果
- $('.validCode_img').click(function () {
- console.log(this)
- this.src+="?"
- })
- 3.注册form组件注意事项
- if form.is_valid():
- username=form.cleaned_data['username'] #如果form过滤验证成功了 就直接在form.cleaned_data内取值就行,不必从request.POST中取值
- password=form.cleaned_data['password']
- email=form.cleaned_data['email']
- tel=form.cleaned_data['tel']
- avatar = request.FILES.get("avatar")
- if not avatar:
- #用户注册时未选取头像,那么在创建新用户时不用创建头像字段,因为在models中已经设置了默认值,不然在数据库中存的会是空
- models.UserInfo.objects.create_user(username=username,password=password,email=email,telephone=tel)
- else:
- models.UserInfo.objects.create_user(username=username,password=password,email=email,telephone=tel,avatar=avatar)
- form组件的局部钩子返回值 : return self.cleaned_data['xxx']
- 全局猴子返回值 : return self.cleaned_data
- #钩子函数中在 clean_data 取值时, 要用 get方法
- 4.头像预览
- <div class="form-group" id="i2">
- {# 注意下面img与input 标签的前后顺序,如颠倒会出现点击图片不出现选择图片窗口 #}
- <label for="avatar">头像</label>
- <img src="/static/img/default.png/" alt="" class="c1" id="i1">
- <input type="file" id="avatar" class="c1">
- </div>
- $("#avatar").change(function () {
- var ele_file=$(this)[0].files[0]; //$(this)[0]和this 一样
- var reader=new FileReader();
- reader.readAsDataURL(ele_file);
- reader.onload=function () {
- $("#i1")[0].src=this.result
- }
- });
- 5.注册时返回的错误信息的处理
- var errors_msg=data1['errors_msg'];
- $.each(errors_msg,function (i,v) {
- {# console.log(i,v);#}
- var ele=$('<span>');
- ele.html(v[0]).addClass('pull-right').css('color','red');
- $('#'+i).after(ele).parent().addClass('has-error')
- if(i=='__all__'){
- $('#repassword').after(ele).parent().addClass('has-error')
- }
- })
- 6.ajax在提交二进制数据时用formData
- var formData=new FormData();
- formData.append('username',$('#username').val());
- formData.append('avatar',$('#avatar')[0].files[0]);
- $.ajax({
- url:'/reg/',
- type:'POST',
- data:formData,
- contentType:false,
- processData:false,
- headers:{"X-CSRFToken":$.cookie('csrftoken')}, #需要引用 <script src="/static/js/jquery.cookie.js"></script>
- #有时引用的cookie.js文件没有效果,那就换成 cdn 引用
- 7.url路由分发与url反向解析
- 根路径配置: url(r'^$', views.index), url是ip+端口时,没有路径,执行index视图函数
- 路由分发:
- '''
- Including another URLconf
- 1. Import the include() function: from django.conf.urls import url, include
- 2. Add a URL to urlpatterns: url()
- '''
- from django.conf.urls import url, include
- url(r'^blog/',include('blog.urls')),
- 反向解析:
- url(r'^(?P<user>.*)/$',views.person_site,name='aaa'),
- <a href="{% url 'aaa' request.user.username %}"></a> #注意 在url反向解析时,如需要参数就必须传
- 8.首页的左侧菜单:
- index.html
- {% for site_category in site_category_list %}
- <div class="panel panel-success">
- <div class="panel-heading site_category">{{ site_category.name }}</div>
- <div class="panel-body hides">
- {% for obj in site_category.sitearticlecategory_set.all %}
- <a href="/cate/{{ obj.name }}/" style="text-decoration: none"><p>{{ obj.name }}</p></a> #在点击相应的分类是显示此分类的所有文章
- {% endfor %}
- </div>
- </div>
- {% endfor %}
- urls.py
- url(r'^cate/(.*)/$', views.index),
- views.py
- def index(request,*args):
- if args:
- article_list = models.Article.objects.filter(site_article_category__name=args[0])
- else:
- article_list=models.Article.objects.all()
- site_category_list=models.SiteCategory.objects.all()
- return render(request,"index.html",{'article_list':article_list,'site_category_list':site_category_list})
- css/js样式:
- <script>
- $('.site_category').mouseover(function () {
- console.log($(this))
- console.log(this) //打印两者的区别???
- $(this).next().slideDown(300)
- }).parent().mouseleave(function () {
- $(this).children('.panel-body').slideUp(300)
- })
- </script>
- 9.头像图片在页面中显示的两种方式:
- <img src="/media/{{ user.user.avatar }}" width="60px" height="60px">
- <img src="{{ user.user.avatar.url }}" width="60px" height="60px">
- 10. media配置:
- settings.py
- MEDIA_ROOT=os.path.join(BASE_DIR,"blog","media","uploads")
- MEDIA_URL="/media/"
- urls.py
- url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
- 用处:
- ----- avatar = models.FileField(verbose_name='头像', upload_to='avatar', default="/avatar/default.png")
- 会把接收的文件放在media指代的路径与upload_to的拼接:
- BASE_DIR/blog/media/uploads/avatar/ xxx图片
- avatar字段在数据库保存的是:avatar/a.png
- ------
- 在页面中显示 <img src="/media/avatar/a.png">
- 11. auth模块: http://www.cnblogs.com/liuwei0824/p/7772525.html
- 12. 个人首页:
- 时间归档:
- date_list=models.Article.objects.filter(user=user_obj).extra(select={"filter_create_date":"strftime('%%Y/%%m',create_time)"}).values_list( "filter_create_date").annotate(Count("nid"))
- 园龄:自定义过滤器用当前的时间对象-创建的时间对象
- 注意:在引用自定义过滤器时 要在body标签下 其他位置浏览器会出现小错误
- 标签与分类归档有两种方式处理:
- 1. 在后端用分组聚合函数处理完成传入前端直接渲染
- 2. 在后端把文章对象传给前端,在前端深度查询进行渲染
- 13. 评论树:
- views.py
- def commentTree(request,article_id):
- time_dict={}
- avatar_dict={}
- comment_all=models.Comment.objects.filter(article_id=article_id)
- for i in comment_all:
- avatar='/media/'+str(i.user.avatar)
- time=str(i.create_time).split('.',1)[0][:-3]
- time_dict[i.nid]=time
- avatar_dict[i.nid]=avatar
- comment_list=models.Comment.objects.filter(article_id=article_id).values('nid','user__username','user__avatar','content','parent_comment_id')
- for i in comment_list:
- if i['nid'] in time_dict:
- i['create_time']=time_dict[i['nid']]
- if i['nid'] in time_dict:
- i['create_user_avatar'] = avatar_dict[i['nid']]
- i['children_list'] = []
- d = {}
- for i in comment_list:
- d[i['nid']] = i
- for i in comment_list:
- if i['parent_comment_id'] in d:
- d[i['parent_comment_id']]['children_list'].append(i)
- li = []
- for i, j in d.items():
- if not j['parent_comment_id']:
- li.append(j)
- # print(li,66666666666666)
- import json
- return HttpResponse(json.dumps(li))
- .html
- <h5>已发表评论(评论树):</h5>
- <div class="comment_tree_list">
- </div>
- $.ajax({
- url:'/blog/commentTree/'+$.cookie('article_obj_nid'),
- type:'get',
- success:function (data) {
- var data=JSON.parse(data);
- <script>
- {# console.log(data[1]);#}
- var s=showCommentTree(data);
- $(".comment_tree_list").append(s);
- }
- })
- function showCommentTree(comment_list) { // comment_list: [{"content":"","children_list":[{}]},{"content":""},{"content":""},]
- var html="";
- $.each(comment_list,function (i,comment_dict) {
- var nid=comment_dict['nid'];
- var val=comment_dict["content"];
- var avatar=comment_dict["create_user_avatar"];
- var create_time=comment_dict["create_time"];
- var comment_username=comment_dict["user__username"];
- var ssss='<div class="row comment_content_haed"><div><span> '+'<img src='+avatar+' alt="" height="25px" width="25px" style="margin-right: 5px"></span> <a href="" style="text-decoration: none" class="comment_color c1">'+comment_username+'</a><span style="margin-left: 10px">'+create_time+'</span><a title="发送站内短消息" class="sendMsg2This" href=""> </a></div><div class="comment_content_body"><p style="margin-left: 18px">'+val+'</p></div><div class="tig_head" comment_pid='+nid+'><a class="pull-right comment_color tig reply" style="text-decoration: none">回复</a><a class="pull-right tig comment_color" style="text-decoration: none">支持({{ comment_obj.up_count }})</a></div></div><hr style="margin-right: 60px">'
- var commnent_str= '<div class="comment"><div class="content"><span>'+ssss+'</span></div>';
- if(comment_dict["children_list"]){
- var s=showCommentTree(comment_dict["children_list"]); // [{},{}]
- commnent_str+=s
- }
- commnent_str+="</div>";
- html+=commnent_str
- });
- return html
- }
- </script>
- 14. 编辑器的防止xss攻击:用form组件过滤出敏感的标签及属性
- forms.py 引用xss
- class ArticleForm(Form):
- content=fields.CharField(required=True,error_messages={'required':'不能为空'},
- widget=widgets.Textarea(attrs={'id':'comment_content'}))
- def clean_content(self):
- from blog.plugins import xss_plugin
- html_str=self.cleaned_data.get("content")
- clean_content=xss_plugin.filter_xss(html_str)
- self.cleaned_data["content"]=clean_content
- return self.cleaned_data.get("content")
- def filter_xss(html_str):
- valid_tag_list = ["p", "div", "a", "img", "html", "body", "br", "strong", "b"]
- valid_dict = {"p": ["id", "class"], "div": ["id", "class"]}
- from bs4 import BeautifulSoup
- soup = BeautifulSoup(html_str, "html.parser") # soup -----> document
- ######### 改成dict
- for ele in soup.find_all():
- # 过滤非法标签
- if ele.name not in valid_dict:
- ele.decompose()
- # 过滤非法属性
- else:
- attrs = ele.attrs # p {"id":12,"class":"d1","egon":"dog"}
- l = []
- for k in attrs:
- if k not in valid_dict[ele.name]:
- l.append(k)
- for i in l:
- del attrs[i]
- print(soup)
- return soup.decode() #默认decode 格式就是utf-8
- 15. 后台管理:增删改查....
- 16. kindeditor 编辑器文本域获取焦点 ???
blog项目知识点梳理的更多相关文章
- Django blog项目知识点总结
数据库操作部分 当我们在Django项目中的models.py下写好创建表的代码后.为了创建好这些数据库表,我们再一次请出我的工程管理助手 manage.py.激活虚拟环境,切换到 manage.py ...
- BBS+Blog项目流程及补充知识点
项目流程: 1. 产品需求 (1)基于用户认证组件和Ajax实现登陆验证(图片验证码) (2)基于forms组件和Ajax实现注册功能 (3)设计系统首页(文章列表渲染) (4)设计个人站点页面 (5 ...
- Django学习笔记(19)——BBS+Blog项目开发(3)细节知识点补充
本文将BBS+Blog项目开发中所需要的细节知识点进行补充,其中内容包括KindEditor编辑器的使用,BeautifulSoup 模块及其防XSS攻击,Django中admin管理工具的使用,me ...
- Memcache知识点梳理
Memcache知识点梳理 Memcached概念: Memcached是一个免费开源的,高性能的,具有分布式对象的缓存系统,它可以用来保存一些经常存取的对象或数据,保存的数据像一张巨大的HAS ...
- [独孤九剑]Oracle知识点梳理(十)%type与%rowtype及常用函数
本系列链接导航: [独孤九剑]Oracle知识点梳理(一)表空间.用户 [独孤九剑]Oracle知识点梳理(二)数据库的连接 [独孤九剑]Oracle知识点梳理(三)导入.导出 [独孤九剑]Oracl ...
- BBS项目知识点汇总
目录 bbs项目知识点汇总 一. JavaScript 1 替换头像 2 form表单拿数据 3 form组件error信息渲染 4 添加html代码 5 聚焦操作 二 . html在线编辑器 三 . ...
- 1+x 证书 Web 前端开发 MySQL 知识点梳理
官方QQ群 1+x 证书 Web 前端开发 MySQL 知识点梳理 http://blog.zh66.club/index.php/archives/199/
- Django学习笔记(18)——BBS+Blog项目开发(2)主体思路及流程
这篇博客主要完成一个BBS+Blog项目,那么主要是模仿博客园的博客思路,使用Django框架进行练习. 准备:项目需求分析 在做一个项目的时候,我们首先做的就是谈清楚项目需求,功能需求,然后才开始写 ...
- Django快速学习搭建blog项目
新手学习Django,本文学习的文档是<Django Web开发指南>.好了我也是新手,没什么好说了,go!- 首先先确定环境,我是在linux(Ubuntu14.04 gnome)下. ...
随机推荐
- 检测浏览器(BOM)以及地址栏网址的API
navigator.userAgent //检测浏览器的版本以及那个厂商的 (不怎么准,你比如360经常跟别人干架,所以别人检测到360浏览器就提示浏览器危险,所以360就自己修改了) //分解这个地 ...
- Math.random 随机数方法
随机取数方法 Math.random() 表示0到1之间随机取一个数 <x< 小数 Math.random()* 表示0<x< parseInt(Math.random()*) ...
- Codeforces 855C. Helga Hufflepuff's Cup----树形DP
z最近在学习树形DP...好难啊. 在cf上找到了一题c题当模版马克一下. 题目不贴了..>>http://codeforces.com/problemset/problem/855/C& ...
- 3、Python迭代器、列表解析及生成器(0530)
1.动态语言 sys.getrefcount() //查看对象的引用计数 增加对象的引用计数场景 对象创建时:以赋值的方式,创建变量名的同时就会创建变量 将对象添加进容器时:类似list.app ...
- 【Ruby】【YAML】
require "YAML" var = YAML.load(File.open('b.yml')) #哈希puts var.class #Hashprint var ," ...
- _faction
一.自定义阵营独立于联盟,部落,联盟和部落玩家可以加入同一阵营 二._function_menu表可以配置自定义阵营开启 二.配合_pvp表,可以实现区域的自定义阵营PVP 三.配合_req表fact ...
- 使用ajax判断登录用户名
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Register.aspx. ...
- Thread.Sleep(0)妙用
Thread.Sleep(0)妙用 我们可能经常会用到 Thread.Sleep 函数来使线程挂起一段时间.那么你有没有正确的理解这个函数的用法呢?思考下面这两个问题: 假设现在是 2008-4-7 ...
- PCA分析和因子分析
#由此说明使用prcomp函数时,必须使用标准化过的原始数据.如果使用没有标准化的raw数据(不是相关系数矩阵或者协方差矩阵),必须将参数scale. = T <result>$sdev ...
- 写给前端的Python依赖管理指北
概述 在Python的项目中,我们可以通过pip来安装依赖包,但是不像npm install,pip默认安装的依赖包会挂在全局上,不利于项目工程协作. 这时候需要一款类似npm的工具记录我们的项目依赖 ...