Django项目开发,XSS攻击,图片防盗链,图片验证码,kindeditor编辑器
一、Django项目开发
1. 项目开发流程
- 创建django项目,创建templates文件夹(pycharm创建django项目时,会自动创建templates文件夹和到settings文件中添加其路径)
- models文件中创建模型表类
- settings文件中注册app,添加静态文件路径,添加templates文件夹路径。
- urls文件中配置视图函数或视图类的路由
- views文件中书写业务逻辑
- templates文件夹中创建并书写前端页面
2. auth模块的补充
(1)django的admin可视化管理页面
只能是超级用户才能登陆操作
在django项目中,我们可以使用django自带的后台管理界面,进行管理员的后台的管理。
要想使用admin可视化管理页面,我们需要先将想要管理的模型表到对应的app文件夹的admin.py文件中注册
注册方法:
from django.contrib import admin
from app01 import models admin.site.register(models.模型表的类名)
(2)将admin可视化管理页面的模型表显示成中文
- 方法:
# 在对应的模型表中书写:
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
def __str__(self):
return self.username
class Meta:
verbose_name_plural = '用户表'
# verbose_name = '用户表' # 会自动加s后缀
(3)auth模块的用户表上传用户头像的bug
- auth模块方法上传头像时,会有bug,所以我们勇士另外一种方式上传用户头像
# 不能用update方法
# 只能用对象点头像属性再赋值,相当于字典中的按key修改值方法,再用对象点save() 来保存(***一定不能忘了保存***)。
# 例子
# 错误演示:
file_obj = request.FILES.get("avatar")
models.Userinfo.objects.filter(pk=request.user.pk).update(avatar=file_obj) # 保存时不会自动拼接文件的路径,只会保存文件名
# 正确操作
file_obj = request.FILES.get("avatar")
request.user.avatar = file_obj # request.user 相当于user.obj
request.user.save()
(4)auth模块提供的登陆装饰器
- auth模块中的登陆认证装饰器,在一个视图函数被装饰上之后,我们如果在没有登录情况下访问,则会
跳转到你定义的登陆页面,在登陆页面的url后面会携带拼接参数——》拼接参数: ?next=被装饰的视图函数的url - 实例:
@login_required
def set_avatar(request):
return HttpResponse('OK')
# 登陆页面的url
127.0.0.1:8000/login?next=视图函数set_avatar对应的url
3. django项目的事务使用实例
# 添加评论表的数据后,并把文章表的评论统计次数加一
from django.db import transaction
with transaction.atomic():
models.Comment.objects.create(user=request.user,article_id=article_id,content=content,parent_id=parent_id)
models.Article.objects.filter(pk=article_id).update(comment_num = F('comment_num') + 1)
back_dic['msg'] = '评论成功'
return JsonResponse(back_dic)
二、django项目的media静态文件夹
media与static文件夹都是约定俗成的一种文件夹的命名
media静态文件夹存放的是用户上传的文件,包括图片、视频、音乐、也可以是文章等
static文件夹中存放的是项目中要用到的css、js、jQuery、字体、文件等
django项目中,对于用户上传的文件,django后端会自动识别,并保存到media文件夹中。当有文件要保存时,会到settings文件中定义的media的路径自动创建media文件夹
1. media文件夹的配置
(1)本地资源暴露给用户配置方法
- 本地任何资源都可以通过下面这种方法暴露给外界,谨慎使用
# 1. settings文件中配置
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# 2. 总路由中配置(注意若不是总路由,如果有路由分发时,可能会出现错误)
from django.views.static import serve
url(r'^media/(?P<path>.*)',serve,{'document_root':settings.MEDIA_ROOT}), # 注意在有名分组后面没有 /
# 使用实例:
# models文件中:
class Userinfo(AbstractUser):
phone = models.BigIntegerField(null=True,blank=True) # blank告诉admin后台管理 该字段可以为空
avatar = models.FileField(upload_to='avatar/',default='media/avatar/default.jpg')
# 该字段你直接传文件即可,会自动将文件保存到avatar文件夹下,没有则会自动创建avatar文件夹,然后数据库里面存文件路径
register_time = models.DateField(auto_now_add=True)
blog = models.OneToOneField(to='Blog',null=True)
templates文件夹的某一html文件中:
<img class="media-object" src="/media/{{ userinfo.avatar }}/" alt="..." height="60">
三、django项目中的小知识点
1. 前端
(1)form表单的serializeArray方法
// from表单的serializeArray()统计所有普通键值对,包括csrf_token
$.each($('#myform').serializeArray(), function (index, obj) {
MyFormDate.append(obj.name, obj.value)
});
(2)img标签的src属性
- img的src属性的值有三种格式
- 资源的绝对路径
- 本网站的图片url
- 直接是二进制数据
(3)FormData对象
- 通过FormData来添加值时,ajax后面一定要指定contentType 和processData 这两个参数,都为false,因为FormData本来是用来传文件时使用的
let MyFormData = new FormData();
// 循环添加键值对
$.each($('#myform').serializeArray(),function (index,obj) {
MyFormData.append(obj.name , obj.value)
}) ;
$.ajax({
url:'',
type:'post',
data:MyFormData,
contentType:false, // 不要使用任何的编码 django能够识别对象自身
processData:false, // 不要让浏览器处理你的数据
success:function (back_data) {}
})
2. 后端
(1)把文章按日期分组查询
from django.db.models import Max,Min,Count,Sum,Avg
from django.db.models.functions import TruncMonth
date_list = models.Article.objects.filter(blog=blog).annotate(month=TruncMonth('create_time')).values('month').annotate(num=Count('pk')).values_list('month','num')
(2)request.path
和 request.get_full_path
# 这是获得全路径的一个方法 /user/register_name/?name=frank 会携带url后面的拼接参数
path = request.get_full_path()
# 这是获得路径的一个属性 /user/register_name/ 不会携带url后面的拼接参数
path = request.path
# os模块
# 在settings文件中
print(os.path.abspath(__file__)) # 绝对路径
print(os.getcwd()) # settings文件的当前路径
# 结果:
D:\DjangoProjects\bbs01\bbs01\settings.py
D:\DjangoProjects\bbs01\bbs01
(3)settings文件中的国际化配置
LANGUAGE_CODE = 'zh-hans' # zh-Hans是简体中文 zh-Hant是繁体中文 ,该字段可以让django的后端数据渲染到前端时,翻译成中文
TIME_ZONE = 'Asia/Shanghai'
# Django设置时区为TIME_ZONE = 'Asia/Shanghai' USE_TZ = True后,存入mysql中的时间只能是UTC时间。这个问题的解释还得看Django官方文档。其实是我理解错了,因为Mysql存储的时间不能灵活设置时区,不像datetime对象有一项参数专门指定时区,所以为了统一全球的时间,必须使用国际标准时间UTC,否则就会乱套。所有时间在存如数据库前,必须转换成UTC时间。比如北京时间8点,存入mysql变成0点(UTC)。
# 设了TIME_ZONE = 'Asia/Shanghai',数据库中存储的所有时间不会改变,还是UTC时间,它的作用是让数据库存储UTC时间在读取时自动转为北京时间(只有前台会自动转换,后台需要手动转换)
USE_I18N = True
USE_L10N = True
USE_TZ = False
(4)TODO注释用法
用法: 因为是注释,所以要加 #
# TODO 注释内容
# 在编辑器的TODO功能窗口可以直接定位到写了TODO注释的位置
四、XSS攻击
1. XXS攻击
- XSS攻击就是别人通过网站提供的上传文件接口向网站服务端上传带有的恶意js脚本,来消耗服务端资源
2. 防止XSS攻击的方法
利用beautifulsoup模块,过滤掉script标签
使用beautifulsoup模块前,要先下载安装:
python pip install bs4
实例
# 先生成一个模块对象
from bs4 import BeautifulSoup
soup = BeautifulSoup(content,'html.parser')
# print(soup.text) # 获取纯文本
ags = soup.find_all()
# print(tags)
for tag in tags:
if tag.name == 'script':
tag.decompose() # 删除script标签 # 文章描述的截取,简单粗暴的直接截取内容的150个字符串
desc = soup.text[0:150]
五、图片防盗链
- 为了防止自己的服务器被当做活雷锋,为其他网站提供服务
- 原理:利用http标准协议中的referer方法
http标准协议中有专门的字段记录referer
一来可以追溯上一个入站地址是什么
二来对于资源文件,可以跟踪到包含显示他的网页地址是什么
因此所有防盗链方法都是基于这个Referer字段
六、图片验证码
- 实际开发中,一般使用网上提供的验证码接口,如百度验证码等
- 生成图片验证码实例
- 用到了两个模块
PIL和io
- 用到了两个模块
自己书写图片验证码:
from PIL import Image,ImageDraw,ImageFont
import random
from io import BytesIO,StringIO
"""
内存管理器模块
BytesIO 保存数据 并且在获取的时候 是以二进制的方式给你
StringIO 保存数据 并且在获取的时候 是以字符串的方式给你
"""
"""
Image 生成图片
ImageDraw 在图片上写字
ImageFont 控制字的字体样式
"""
# 图片验证码
def get_random():
return random.randint(0,255),random.randint(0,255),random.randint(0,255)
def get_code(request):
# 步骤一:生成图片(两种方式)
# 方式一:直接使用本地图片,发送到前端
# with open('avatar/03.jpg','rb')as fr:
# data = fr.read()
#
# return HttpResponse(data)
# 方式二:利用pillow模块自动生成图片,保存到本地后在发送到前端
# 生成图片对象
# img_obj = Image.new('RGB',(360,35),get_random())
#
# # 将图片保存在本地
# with open('yanzhengma.png','wb')as fw:
# img_obj.save(fw,'png')
#
# # 利用文件操作将图片数据读取并发送到前端
# with open('yanzhengma.png','rb')as fr:
# data = fr.read()
# return HttpResponse(data)
# 步骤二:临时存储数据到能够随时取出的地方
# 生成一个图片对象
# img_obj = Image.new('RGB',(360,35),get_random())
#
# # 再生成一个io对象,这个对象相当于文件对象的句柄
# io_obj = BytesIO()
#
# # 把数据临时存储到io_obj中
# img_obj.save(io_obj,'png')
#
# # 读取并发送到前端数据
# return HttpResponse(io_obj.getvalue())
# 步骤三(完整写法):
# 生成图片对象
img_obj = Image.new('RGB',(360,35),get_random())
# 将生成的图片交给ImageDraw,生成一个笔画对象
img_draw = ImageDraw.Draw(img_obj)
# 指定字体样式
img_font = ImageFont.truetype('static/Font/simhei.ttf',30)
# 生成随机验证码(在图片上写字)
code = ''
for i in range(5):
upper_str = chr(random.randint(65,90)) # 随机大写字母
lower_str = chr(random.randint(97,122)) # 随机小写字母
num_str = str(random.randint(0,9)) # 随机数字
tmp = random.choice([upper_str, lower_str, num_str])
img_draw.text((i*60+60,0),tmp, get_random(), img_font)
code += tmp
print(code)
request.session['code'] = code
io_obj = BytesIO() # io_obj就相当于文本操作中的句柄
img_obj.save(io_obj,'png')
return HttpResponse(io_obj.getvalue())
七、kindeditor编辑器基本使用
- 详细用法直接查看kindeditor官方文档
# 前端页面中
<p>
<textarea name="content" id="id_comment" cols="30" rows="10" class="form-control"></textarea>
</p>
<script>
KindEditor.ready(function (K) {
window.editor = K.create('#id_comment',{
width: '100%',
height:'450px',
resizeType:0,
uploadJson : '/upload_img/', // kindeditor编辑器上传图片
extraFileUploadParams : {
csrfmiddlewaretoken : '{{ csrf_token }}',
}
});
});
</script>
# kindeditor编辑器上传图片后端代码
# urls文件中:
url(r'^upload_img/',views.upload_img),
# views文件中:
import os
from BBS import settings
def upload_img(request):
back_dic = {'error': 0}
# 获取用户上传的图片 然后保存到本地
if request.method == 'POST':
# print(request.FILES) 打印键值对
file_obj = request.FILES.get('imgFile') # imgFile是kindeditor提供的文件对象对应的key
# 手动拼接文件存储的文件路径
file_path = os.path.join(settings.BASE_DIR,'media','article_img')
if not os.path.isdir(file_path):
os.mkdir(file_path)
# 文件操作
# 手动拼接文件名全路径
img_path = os.path.join(file_path,file_obj.name)
with open(img_path,'wb') as f:
for line in file_obj:
f.write(line)
_url = '/media/article_img/%s'%file_obj.name
back_dic['url'] = _url
"""
//成功时
{
"error" : 0,
"url" : "http://www.example.com/path/to/file.ext"
}
//失败时
{
"error" : 1,
"message" : "错误信息"
}
"""
return JsonResponse(back_dic)
Django项目开发,XSS攻击,图片防盗链,图片验证码,kindeditor编辑器的更多相关文章
- 第十三节:HttpHander扩展及应用(自定义扩展名、图片防盗链)
一. 自定义扩展名 1. 前言 凡是实现了IHttpHandler接口的类均为Handler类,HttpHandler是一个HTTP请求的真正处理中心,在HttpHandler容器中,ASP.NET ...
- Asp.net MVC3中全局图片防盗链
怎么样在Asp.Net MVC3中做到全局图片防盗链?如果熟悉Asp.Net的页面生命周期,相信解决这个问题应该很容易.下面就演示一下如何去做? 一.首先是全局的,我们肯定要在Global.asax文 ...
- webform的图片防盗链
最近用到域的问题,不是同一主机的请求将不允许请求此页面. 这其实和图片防盗链的本质是一样的. 通过两个属性:由于当时用的aspx视图引擎,所以需要通过HttpContext.Current才能拿到ht ...
- Typora--终于找到一个能够解决将csdn文章同步到hexo的完美编辑器(解决csdn图片防盗链导致无法直接复制文章的问题)。
文章目录 需求 背景 新宠 告诉我,我的名字叫什么?大声点我听不见~ 页面 神奇之处 看得见的优点 如何设置项目根目录 如何显示图片? 于是最终操作流程 个人博客:https://mmmmmm.me ...
- Nginx中防盗链(下载防盗链和图片防盗链)操作记录
日常运维工作中,设置防盗链的需求会经常碰到,这也是优化网站的一个必要措施.今天在此介绍Nginx中设置下载防盗链和图片防盗链的操作~ 一.Nginx中下载防盗链的操作记录对于一些站点上的下载操作,有很 ...
- nginx配置图片防盗链
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)${ expires 30d; access_log off; valid_referers none blocked ...
- ASP.NET 实现简单的图片防盗链介绍
在此,网站图片防盗链的方法是,通过获取Http请求头中的 Referer 标头与本网站域名比较,来判断用户是否来自本站跳转过来的 . 创建一个全局处理程序,用来处理images目录下的图片的直接请求: ...
- Nginx修改配置实现图片防盗链
一般情况下,防盗链是针对软件下载和图片的,由于一般的站点不提供资源下载,所以本文主要是针对图片的防盗链 1.如果对全站图片做防盗链,至少需要一个另外的域名存放指向图片.因为如果对全站图片做了防盗链,包 ...
- CSS代码实现图片防盗链
CSS代码实现图片防盗链的方法其实很简单.在CSS文件中添加以下代码: img { filter:exPRession( this.不能去掉 ? "" : ( (!this.com ...
随机推荐
- RFID/13.56MHZ/NFC线圈防干扰原理-附磁导材料防干扰原理 20191128
RFID/13.56MHZ/NFC之间采用电磁感应方式进行通信. 1.铁氧体.硅钢片等导磁材料的相对磁导率比较高,多年前在变压器中已经有广泛的应用.有防止磁通饱和,提高变压器感应效率的作用. 2.RF ...
- 16.Azkaban的安装
工作流调度器azkaban 2.1 概述 2.1.1为什么需要工作流调度系统 l 一个完整的数据分析系统通常都是由大量任务单元组成: shell脚本程序,java程序,mapreduce程序.hiv ...
- linux 静态库 ar命令用法
当我们的程序中有经常使用的模块,而且这种模块在其他程序中也会用到,这时按照软件重用的思想,我们应该将它们生成库,使得以后编程可以减少开发代码量.这里介绍命令ar,用来对库操作. 1.ar基本用法 ar ...
- 【LOJ】#3109. 「TJOI2019」甲苯先生的线段树
LOJ#3109. 「TJOI2019」甲苯先生的线段树 发现如果枚举路径两边的长度的话,如果根节点的值是$x$,左边走了$l$,右边走了$r$ 肯定答案会是$(2^{l + 1} + 2^{r + ...
- 解决github pages和github .md文件图片不显示
博客园上传的图片,在github上无法显示. 在github项目下建立img文件夹,放上图片 两种方式 项目绝对路径 https://raw.githubusercontent.com/用户名/项目名 ...
- 执行sql语句,不依靠实体 获取string值
IList<string> list2 = Session.CreateSQLQuery(sql.ToString()).List<string>();
- 数据库数据导入/导出报错:无法在只读列“Id”中插入数据。
本文仅供小白参考,大佬请随意...... 本例是:从vs 2017自带的localDB数据库的数据---导出到---->Sql Server 2008中的相应数据库中 1. 导出数据库: 2. ...
- gridview单元格编辑添加数据
行号 private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIn ...
- Navicat连接CentOS7中的MariaDB
Step 1:首先登录数据库设置开启远程连接 mysql -u root -p Step 2:使用改表法实现远程连接 use mysql; update user set host = '%' whe ...
- Redis-设置key过期
Redis-设置key过期 expire key seconds 设置指定key 多少秒后过期, seconds 为 -1 时表示永不过期 ttl key 查看指定key还有多少秒过期 persist ...