第三百九十节,Django+Xadmin打造上线标准的在线教育平台—Django+cropper插件头像裁剪上传
第三百九十节,Django+Xadmin打造上线标准的在线教育平台—Django+cropper插件头像裁剪上传
实现原理
前台用cropper插件,将用户上传头像时裁剪图片的坐标和图片,传到逻辑处理函数里,在逻辑处理函数里接收原始图片进行保存,然后接收用户的裁剪坐标,利用python的Pillow模块图像处理模块里的PIL(图像库),将原始图片根据用户裁剪坐标进行裁剪
有两个重点:第一要准备好cropper头像裁剪插件,第二python环境要安装好Pillow模块
htnl页面
编写htnl页面,引入cropper插件相关的css和js文件
注意:下面红色背景的地方不要忘记设置,否则表单无法提交到后台
<!DOCTYPE html>
<html lang="en">
{% load staticfiles %} {# 启用静态文件引用#}
<head>
<meta charset="UTF-8">
<title>Document</title>
<link href="{% static 'tou_xiang/bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'tou_xiang/font-awesome/css/font-awesome.min.css' %}" rel="stylesheet">
<link href="{% static 'tou_xiang/cropper/cropper.min.css' %}" rel="stylesheet">
<link href="{% static 'tou_xiang/sitelogo/sitelogo.css' %}" rel="stylesheet">
</head>
<body>
{# 头像上传开始----------------------------------- #}
{# 头像区块 #}
<div class="ibox-content">
<div class="row">
<div id="crop-avatar" class="col-md-6">
<div class="avatar-view" title="点击上传头像">
<img src="{{ MEDIA_URL }}{% for ch in ch_username %}{{ ch.image }}{% endfor %}"
data-am-popover="{content: '点击上传头像', trigger: 'hover focus'}">
</div>
</div>
</div>
</div>
{# 上传弹出框 #}
<div class="modal fade" id="avatar-modal" aria-hidden="true" aria-labelledby="avatar-modal-label" role="dialog"
tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<form class="avatar-form" action="{% url 'touxiang' %}" enctype="multipart/form-data" method="post">
<div class="modal-header">
<button class="close" data-dismiss="modal" type="button">×</button>
<h4 class="modal-title" id="avatar-modal-label">上传图片</h4>
</div>
<div class="modal-body">
<div class="avatar-body">
<div id="avatar-upload" class="avatar-upload">
<input class="avatar-src" name="avatar_src" type="hidden">
<input class="avatar-data" name="avatar_data" type="hidden">
<label for="avatarInput">
<input class="avatar-input" id="avatarInput" name="avatar_file" type="file">
<div class="tup btn btn-primary" dir="ltr">
<span class="glyphicon glyphicon-cloud"></span>
上传文件
</div>
</label>
</div>
<div class="row">
<div class="col-md-9">
<div class="avatar-wrapper"></div>
</div>
<div class="col-md-3">
<div class="avatar-preview preview-lg"></div>
{#<div class="avatar-preview preview-md"></div>#}
{#<div class="avatar-preview preview-sm"></div>#}
</div>
</div>
<div class="row avatar-btns">
<div class="col-md-4">
<div class="btn-group">
<button class="btn btn-primary" data-method="rotate" data-option="-90" type="button"
title="Rotate -90 degrees"><i class="fa fa-undo"></i> 向左旋转
</button>
</div>
<div class="btn-group">
<button class="btn btn-primary" data-method="rotate" data-option="90" type="button"
title="Rotate 90 degrees"><i class="fa fa-repeat"></i> 向右旋转
</button>
</div>
</div>
<div class="col-md-5" style="text-align: right;">
<button class="btn btn-primary fa fa-arrows" data-method="setDragMode" data-option="move"
type="button" title="移动">
</button>
<button type="button" class="btn btn-primary fa fa-search-plus" data-method="zoom"
data-option="0.1" title="放大图片">
</button>
<button type="button" class="btn btn-primary fa fa-search-minus" data-method="zoom"
data-option="-0.1" title="缩小图片">
</button>
<button type="button" class="btn btn-primary fa fa-refresh" data-method="reset"
title="重置图片">
</button>
</div>
<div class="col-md-3">
<button id="txiangform" class="btn btn-primary btn-block avatar-save" type="submit">
<i class="fa fa-save"></i> 保存修改
</button>
</div>
</div>
</div>
</div>
{% csrf_token %}
</form>
</div>
</div>
</div>
{# 头像上传结束------------------------------------- #}
<script src="{% static 'tou_xiang/jquery.min.js' %}"></script>
<script src="{% static 'tou_xiang/bootstrap/js/bootstrap.min.js' %}"></script>
<script src="{% static 'tou_xiang/cropper/cropper.min.js' %}"></script>
<script src="{% static 'tou_xiang/sitelogo/sitelogo.js' %}"></script>
</body>
</html>
效果图

专门给上传头像配置一个url路由映射
urlpatterns = [
url(r'usercenter_info.html', usercenter_info.as_view(), name='usercenter_info'),
# 上传头像
url(r'touxiang/', touxiang.as_view(), name='touxiang')
]
forms.py文件编写头像表单验证
#!/usr/bin/env python
# -*- coding:utf8 -*-
from django import forms # 导入Django的表单验证模块
from app_users.models import Users # 导入数据库表类 class touxiangForm(forms.Form):
avatar_file = forms.ImageField()
views.py编写逻辑
import json
from django.shortcuts import render, HttpResponse, redirect # 导入django向浏览器返回方法
from django.views.generic.base import Viewfrom pure_pagination import Paginator, EmptyPage, PageNotAnInteger from app_organization.models import CityDict, CourseOrg # 数据库表
from app_users.models import Users
from app_organization.forms import touxiangForm
from utils.uploadfile import Uploadfile class touxiang(View):
def post(self, request):
usern = request.session.get("username") # 获取用户登录名称
us = Users.objects.filter(username=usern) # 到数据库查找用户
yanzh = touxiangForm(request.POST, request.FILES) # 验证表单
if yanzh.is_valid(): # 表单验证通过
erf = request.FILES['avatar_file'] # 获取上传图片
jetu = request.POST['avatar_data']
# 将上传图片传入一个自定义函数里裁剪,返回图片路径
fanhui = Uploadfile('image', erf, jetu) us.update(image=fanhui) # 将图片路径修改到当前会员数据库
# 向前台返回一个json,result值是图片路径
return HttpResponse(json.dumps({'result': '/media/' + fanhui}))
else:
return HttpResponse("验证失败")
编写Uploadfile截图函数
#!/usr/bin/env python
# -*- coding:utf8 -*-
import os
import time
import random # 引入随机模块文件
import re
import json from PIL import Image from MxOnline.settings import MEDIA_ROOT # 导入配置文件里的上传资源路径 def Uploadfile(mu_lu, wen_jian, jetu):
"""
第一参数,上传头像数据库models里指定的目录名称【字符串类型】
第二参数,接收文件上传对象inMemoryUploadedFile对象【inMemoryUploadedFile对象】
第三参数,接收头像要截图的坐标,x.y.width.height【json类型】
裁剪成功返回图片路径
"""
if not MEDIA_ROOT:
return '请在settings.py配置上传文件目录' try:
nian_yue = time.strftime('%Y/%m/')
pj_mu_lu = os.path.abspath(os.path.join(MEDIA_ROOT, mu_lu, nian_yue)) # 拼接上传路径
pd_mu_lu = os.path.exists(pj_mu_lu)
if pd_mu_lu: # 判断上传目录是否存在
pass
else:
os.makedirs(pj_mu_lu) # 创建上传目录 # 接收文件上传对象inMemoryUploadedFile对象
wenjian = wen_jian
name = wenjian.name # 获取文件名称
size = wenjian.size # 文件大小(字节) # 调用随机函数(随机数开始范围,随机数结束范围)
f1 = str(random.randrange(1, 99999999))
f2 = str(time.strftime('%Y%m%d%H%M%S'))
f3 = str(f2 + f1)
houzh = re.findall('.*\.(.*)', name)[0]
wj_name = f3 + '.' + houzh
xie_ru_lu_jing = pj_mu_lu + '/' + wj_name
# print(xie_ru_lu_jing) # 以读写字节模式打开,存在覆盖没有创建
gshi = 'BMP,PNG,GIF,JPG,JPEG'
pd_gshi = re.findall(houzh.upper(), gshi)
if pd_gshi:
xieru = open(xie_ru_lu_jing, 'wb')
for chunk in wenjian.chunks(): # 循环文件数据块
xieru.write(chunk) # 写入文件
xieru.close() # 关闭
else:
return '上传的不是图片文件' # 判断文件是否写入成功返回布尔值
pd_xieru = os.path.exists(xie_ru_lu_jing) if pd_xieru: # 开始根据前台提供的坐标截图
zuo_biao = json.loads(jetu) # 获取坐标
t_x = int(zuo_biao['x'])
t_y = int(zuo_biao['y'])
t_width = t_x + int(zuo_biao['width'])
t_height = t_y + int(zuo_biao['height']) # 打开要截图的图片
im = Image.open(xie_ru_lu_jing)
# print(xie_ru_lu_jing)
# 裁剪图片,裁剪尺寸为200*200,可以在resize()设置
crop_im = im.convert("RGBA").crop((t_x, t_y, t_width, t_height)).resize((200, 200), Image.ANTIALIAS) # 设置背景颜色为白色
out = Image.new('RGBA', crop_im.size, (255, 255, 255))
out.paste(crop_im, (0, 0, 200, 200), crop_im) # 保存图片
crop_im.save(xie_ru_lu_jing) # 返回图片路径,从第一个参数目录开始的
wj_lj = mu_lu + '/' + nian_yue + wj_name
return wj_lj except Exception as e:
return e
最终效果

第三百九十节,Django+Xadmin打造上线标准的在线教育平台—Django+cropper插件头像裁剪上传的更多相关文章
- 第三百七十八节,Django+Xadmin打造上线标准的在线教育平台—django自带的admin后台管理介绍
第三百七十八节,Django+Xadmin打造上线标准的在线教育平台—django自带的admin后台管理介绍 配置django的admin数据库管理后台 首先urls.py配置数据库后台路由映射,一 ...
- 第三百九十九节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5安装mysql5.6
第三百九十九节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5安装mysql5.6 1.检测系统是否已经安装过mysql或其依赖,若已装过要先将其删除,否则第4步 ...
- 第三百九十六节,Django+Xadmin打造上线标准的在线教育平台—其他插件使用说,自定义列表页上传插件
第三百九十六节,Django+Xadmin打造上线标准的在线教育平台—其他插件使用说,自定义列表页上传插件 设置后台列表页面字段统计 在当前APP里的adminx.py文件里的数据表管理器里设置 ag ...
- 第三百九十五节,Django+Xadmin打造上线标准的在线教育平台—Xadmin集成富文本框
第三百九十五节,Django+Xadmin打造上线标准的在线教育平台—Xadmin集成富文本框 首先安装DjangoUeditor3模块 Ueditor HTML编辑器是百度开源的HTML编辑器 下载 ...
- 第三百九十四节,Django+Xadmin打造上线标准的在线教育平台—Xadmin后台进阶开发配置2,以及目录结构说明
第三百九十四节,Django+Xadmin打造上线标准的在线教育平台—Xadmin后台进阶开发配置2,以及目录结构说明 设置后台列表页面可以直接修改字段内容 在当前APP里的adminx.py文件里的 ...
- 第三百九十八节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5系统环境设置
第三百九十八节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5系统环境设置 1.Linux安装配置 注意事项: 虚拟机网卡桥接模式 不要拨VPN 如果,网络怎么都 ...
- 第三百九十七节,Django+Xadmin打造上线标准的在线教育平台—其他插件使用说,主题本地化设置
第三百九十七节,Django+Xadmin打造上线标准的在线教育平台—其他插件使用说,主题本地化设置 主题设置是在xadmin\plugins\themes.py这个文件 默认xadmin是通过下面这 ...
- 第三百九十三节,Django+Xadmin打造上线标准的在线教育平台—Xadmin后台进阶开发配置
第三百九十三节,Django+Xadmin打造上线标准的在线教育平台—Xadmin后台进阶开发配置 设置后台某个字段的排序规则 在当前APP里的adminx.py文件里的数据表管理器里设置 order ...
- 第三百九十一节,Django+Xadmin打造上线标准的在线教育平台—404,403,500页面配置
第三百九十一节,Django+Xadmin打造上线标准的在线教育平台—404,403,500页面配置 路由映射在全局也就是根目录里的urls.py里配置404路由映射 注意:不是写在urlpatter ...
随机推荐
- 菜鸟译文(一)——Java中的继承和组合
阅读英文的能力对于程序员来说,是很重要的.这几年也一直在学习英文,今天心血来潮,就在网上找了一篇简短的博文翻译一下.水平一般,能力有限,还请各位看官多多指点. 译文: 本文将会举例说明Java中继承和 ...
- Quantum Computation and Quantum Information
https://www.amazon.com/Quantum-Computation-Information-10th-Anniversary/dp/1107002176/ref=asap_bc?ie ...
- [Windows Azure] How to Create and Deploy a Cloud Service?
The Windows Azure Management Portal provides two ways for you to create and deploy a cloud service: ...
- (原创)c++11改进我们的程序之垃圾回收
c#和java中有自动垃圾回收机制,.net运行时和java虚拟机可以管理分配的堆内存,在对象失去引用时自动回收,因此在c#和jva中, 内存管理不是大问题.c++语言没有垃圾回收机制,必须自己去释放 ...
- 解决jar格式文件,双击不能直接运行问题
前提: 安装了JDK 步骤: 1.先右击jar文件,打开方式->选择默认程序->浏览,选中jre下bin文件中javaw.exe(比如我的javaw.exe在C:\Program Fil ...
- zipkin微服务调用链分析
1.zipkin的作用 在微服务架构下,一个http请求从发出到响应,中间可能经过了N多服务的调用,或者N多逻辑操作, 如何监控某个服务,或者某个逻辑操作的执行情况,对分析耗时操作,性能瓶颈具有很大价 ...
- webpack学习文档
webpack课程 目录 第1章 webpack简介... 1 1.1 webpack是什么?... 1 1.2 官网地址... 2 1.3 为什么使用 webpack?... 3 ...
- std::bind()图解
参考:http://blog.think-async.com/2010/04/bind-illustrated.html 避免链接失效,就把文中图转过来了,这几张就清楚的说明了bind的用法和原理.
- 05-老马jQuery教程-动画
前言 jQuery的动画系统做的非常出色,而且把最常用的显示.隐藏.淡入淡出.滑动显示和折叠凳效果都做了很好的封装.跟jQuery的选择器和事件配合起来,可以实现很多很绚的效果,而且简单易用兼容性好. ...
- Python与操作系统有关的模块
Os模块 Python的标准库中的os模块主要涉及普遍的操作系统功能.可以在Linux和Windows下运行,与平台无关.os.sep 可以取代操作系统特定的路径分割符.os.name字符串指示你正在 ...