前言:本文是学习网易微专业的《python全栈工程师 - Django快速建站》课程的笔记,欢迎学习交流。同时感谢老师们的精彩传授!
AJAX
Django
项目中使用AJAX
技术JS
插件AJAX
AJAX:
全称是 Asynchronous JavaScript and XML
, 即异步JavaScript
和XML
。它可以用JavaScript
向服务器发送必要数据,数据格式有XML
和JSON
格式的,同时,AJAX
也可以接收服务器的反馈。JS
插件JS
插件实操一: 下载并导入ImgCrop
插件
ImgCrop
地址:https://github.com/qiwsir/DjangoPracticeProject/tree/master/ImgCrop
Step1
:将imgCrop
插件的css
和js
文件拷贝到项目的static
目录下:
CSS
文件:将imgCrop/css/style.css
文件复制到myproject/static/css/
目录下,并重命名为imagecrop.css
。
JS
文件:将imgCrop/js/
目录下的cropbox-min.js、cropbox.js、jquery-1.11.1.min.js
复制到myproject/static/js/
目录下。
Step2
:修改imagecrop.css
文件:
.
.
.
.container {
width: 400px;
/*将下面这一行注释,并修改后面的一 行*/
/*margin: 40px auto 0 auto;*/
margin: 0 auto 0 0;
position: relative;
font-family: 微软雅黑;
font-size: 12px;
}
.
.
.
实操二: 测试ImgCrop
插件是否可用
Step1
:新增my_image()
视图函数。
编辑文件myproject/account/views.py
.
.
.
# 新增下面这个视图函数,在这里是测试imagecrop插件是否可用
def my_image(request):
return render(request, 'account/imagecrop.html',)
Step2
:新建模板文件myproject/templates/account/imagecrop.html
{% load staticfiles %}
<link rel="stylesheet" href="{% static 'css/imagecrop.css' %}" type="text/css" />
<div class="container">
<div class="imageBox">
<div class="thumbBox">div>
<div class="spinner" style="display: none">div>
div>
<div class="action">
<div class="new-contentarea tc"> <a href="javascript:void(0)" class="upload-img">
<label for="upload-file">请先选择图片...label>
a>
<input type="file" class="" name="upload-file" id="upload-file" />
div>
<input type="button" id="btnCrop" class="Btnsty_peyton" value="OK">
<input type="button" id="btnZoomIn" class="Btnsty_peyton" value="+" >
<input type="button" id="btnZoomOut" class="Btnsty_peyton" value="-" >
div>
<div class="cropped">div>
div>
<script type="text/javascript" src="{% static 'js/jquery-1.11.1.min.js' %}">script>
<script type="text/javascript" src="{% static 'js/cropbox.js' %}">script>
<script type="text/javascript">
$(window).load(function() {
//$('#btnCrop').click();$("#idName").css("cssText","background-color:red!important");
//$(".imageBox").css("cssText","background-position:88px 88px!important");$(".imageBox").css("cssText","background-size:222px 222px!important");
var options =
{
thumbBox: '.thumbBox',
spinner: '.spinner',
imgSrc: ''
}
var cropper = $('.imageBox').cropbox(options);
var img="";
$('#upload-file').on('change', function(){
var reader = new FileReader();
reader.onload = function(e) {
options.imgSrc = e.target.result;
cropper = $('.imageBox').cropbox(options);
getImg();
}
reader.readAsDataURL(this.files[0]);
this.files = [];
//getImg();
})
$('#btnCrop').on('click', function(){
alert("图片上传喽");
})
function getImg(){
img = cropper.getDataURL();
$('.cropped').html('');
$('.cropped').append('+img+'" align="absmiddle" style="width:180px;margin-top:4px;border-radius:180px;box-shadow:0px 0px 12px #7E7E7E;">180px*180px
');
$('.cropped').append('+img+'" align="absmiddle" style="width:128px;margin-top:4px;border-radius:128px;box-shadow:0px 0px 12px #7E7E7E;">128px*128px
');
$('.cropped').append('+img+'" align="absmiddle" style="width:64px;margin-top:4px;border-radius:64px;box-shadow:0px 0px 12px #7E7E7E;" >64px*64px
');
}
$(".imageBox").on("mouseup",function(){
getImg();
});
$('#btnZoomIn').on('click', function(){
cropper.zoomIn();
})
$('#btnZoomOut').on('click', function(){
cropper.zoomOut();
})
});
script>
body>
html>
Step3
:配置路由。myproject/account/urls.py
文件增加如下路由:
.
.
.
path('my-image/', views.my_image, name='my_image'),
UserInfo
模型类:photo = models.ImageField(blank=True)
UserInfoForm
中增加photo
字段实操三:
Step1
: UserInfo
模型类中添加 photo
字段
编辑文件myproject/account/models.py
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
# 一对一关系
user = models.OneToOneField(User, on_delete=models.CASCADE, unique=True)
phone = models.CharField(max_length=20, null=True)
def __str__(self):
return 'user {}'.format(self.user.username)
class UserInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, unique=True)
company = models.CharField(max_length=100, blank=True)
profession = models.CharField(max_length=100, blank=True)
aboutme = models.TextField(blank=True)
# 新增下面这一行
photo = models.ImageField(blank=True)
def __str__(self):
return "user:{}".format(self.user.username)
说明:
添加的是ImageField()
,会要求安装Pillow
模块,没安装的运行下面命令安装即可:
pip install Pillow
Step2
:迁移数据
python manage.py makemigrations
python manage.py migrate
Step3
:在表单类UserInfoForm
中增加photo
字段
.
.
.
class UserInfoForm(forms.ModelForm):
class Meta:
model = UserInfo
# 下面这和,添加 photo 字段
fields = ('company', 'profession', 'aboutme', 'photo')
Step4
:编写视图函数my_image()
,接收图片,并保存。
.
.
.
# 将实操二中的视图函数修改为如下:
@login_required
def my_image(request):
if request.method == 'POST':
img = request.POST['img']
userinfo = UserInfo.objects.get(user=request.user.id)
userinfo.photo = img
userinfo.save()
return HttpResponse('1')
return render(request, 'account/imagecrop.html',)
说明:
1).上传图片必须是登录用户才可用,因此用@login_required
2).图片是以base64
格式保存到数据库中的。
AJAX
./account/imagecrop.html
,使用ajax
上传头像。./account/myself.html
,用来显示头像。实操四:
step1
: 编辑myproject/account/imagecrop.html
,使用ajax
上传头像。
{% load staticfiles %}
<link rel="stylesheet" href="{% static 'css/imagecrop.css' %}" type="text/css" />
<div class="container">
<div class="imageBox">
<div class="thumbBox">div>
<div class="spinner" style="display: none">div>
div>
<div class="action">
<div class="new-contentarea tc"> <a href="javascript:void(0)" class="upload-img">
<label for="upload-file">请先选择图片...label>
a>
<input type="file" class="" name="upload-file" id="upload-file" />
div>
<input type="button" id="btnCrop" class="Btnsty_peyton" value="OK">
<input type="button" id="btnZoomIn" class="Btnsty_peyton" value="+" >
<input type="button" id="btnZoomOut" class="Btnsty_peyton" value="-" >
div>
<div class="cropped">div>
div>
<script type="text/javascript" src="{% static 'js/jquery-1.11.1.min.js' %}">script>
<script type="text/javascript" src="{% static 'js/cropbox.js' %}">script>
<script type="text/javascript">
$(window).load(function() {
//$('#btnCrop').click();$("#idName").css("cssText","background-color:red!important");
//$(".imageBox").css("cssText","background-position:88px 88px!important");$(".imageBox").css("cssText","background-size:222px 222px!important");
var options =
{
thumbBox: '.thumbBox',
spinner: '.spinner',
imgSrc: ''
}
var cropper = $('.imageBox').cropbox(options);
var img="";
$('#upload-file').on('change', function(){
var reader = new FileReader();
reader.onload = function(e) {
options.imgSrc = e.target.result;
cropper = $('.imageBox').cropbox(options);
getImg();
}
reader.readAsDataURL(this.files[0]);
this.files = [];
//getImg();
})
$('#btnCrop').on('click', function(){
//alert("图片上传喽");
// 新增下面的ajax
$.ajax({
url: '{% url "account:my_image" %}',
type: 'POST',
data: {'img': img},
success: function(e) {
location.href="{% url 'account:aboutme' %}"
}
}, 'JSON')
})
function getImg(){
img = cropper.getDataURL();
$('.cropped').html('');
$('.cropped').append('+img+'" align="absmiddle" style="width:180px;margin-top:4px;border-radius:180px;box-shadow:0px 0px 12px #7E7E7E;">180px*180px
');
$('.cropped').append('+img+'" align="absmiddle" style="width:128px;margin-top:4px;border-radius:128px;box-shadow:0px 0px 12px #7E7E7E;">128px*128px
');
$('.cropped').append('+img+'" align="absmiddle" style="width:64px;margin-top:4px;border-radius:64px;box-shadow:0px 0px 12px #7E7E7E;" >64px*64px
');
}
$(".imageBox").on("mouseup",function(){
getImg();
});
$('#btnZoomIn').on('click', function(){
cropper.zoomIn();
})
$('#btnZoomOut').on('click', function(){
cropper.zoomOut();
})
});
script>
body>
html>
说明:
1).data:{"img":img}
里的"img"
对应my_image()
视图函数里的request.POST['img']
2).img
对应getImg()
函数里的img = cropper.getDataURL();
Step2
:编辑myproject/account/myself.html
,用来显示头像。
{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}my information{% endblock %}
{% block content %}
<div class="row text-center vertical-middle-sm">
<h1>个人信息h1>
<div class="row">
<div class="col-md-6">
<div class="row">
<div class="col-md-4 text-right"><span>用户名:span>div>
<div class="col-md-8 text-left">{{ user.username }}div>
div>
<div class="row">
<div class="col-md-4 text-right"><span>邮箱:span>div>
<div class="col-md-8 text-left">{{ user.email }}div>
div>
<div class="row">
<div class="col-md-4 text-right"><span>电话:span>div>
<div class="col-md-8 text-left">{{ userprofile.phone }}div>
div>
<div class="row">
<div class="col-md-4 text-right"><span>公司:span>div>
<div class="col-md-8 text-left">{{ userinfo.company }}div>
div>
<div class="row">
<div class="col-md-4 text-right"><span>职业:span>div>
<div class="col-md-8 text-left">{{ userinfo.profession }}div>
div>
<div class="row">
<div class="col-md-4 text-right"><span>个人介绍:span>div>
<div class="col-md-8 text-left">{{ userinfo.aboutme }}div>
div>
<a href="{% url 'account:editme' %}">
<button class="btn btn-primary btn-lg">edit my informationbutton>
a>
div>
<div class="col-md-6">
<div style="margin-right: 100px">
{% if userinfo.photo %}
<img src="{{ userinfo.photo | striptags }}" alt="" class="img-circle" id="my_photo">
{% else %}
<img src="{% static 'images/djbook.png' %}" alt="">
{% endif %}
div>
<div style="margin-right:100px">
<button class="btn btn-primary btn-lg" id="upload_image" onclick="upload_image_layer()">上传头像button>
div>
div>
div>
div>
{% endblock %}
说明:
1).注意要加入{% load staticfiles %}
这一句,表示要加载静态资源。
2).striptags
表示过滤掉userinfo.photo
里的html
标签
Step3
:拷贝csrf.js
文件到myproject/static/js/
下,并在 myproject/templates/account/imagecrop.html
文件中引入csrf.js
.
.
.
<script type="text/javascript" src="{% static 'js/jquery-1.11.1.min.js' %}">script>
<script type="text/javascript" src="{% static 'js/cropbox-min.js' %}">script>
<script type="text/javascript" src="{% static 'js/csrf.js' %}">script>
.
.
.
Step4
:下载并引入layer.js
。
下载地址:http://layer.layui.com/?alone。
将解压后将layer
文件夹里的layer.js、mobile、theme
文件拷贝到项目下的static/js/
目录里。
在文件myproject/templates/account/myself.html
里引入layer.js
{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}my information{% endblock %}
{% block content %}
<div class="row text-center vertical-middle-sm">
<h1>个人信息h1>
<div class="row">
<div class="col-md-6">
<div class="row">
<div class="col-md-4 text-right"><span>用户名:span>div>
<div class="col-md-8 text-left">{{ user.username }}div>
div>
<div class="row">
<div class="col-md-4 text-right"><span>邮箱:span>div>
<div class="col-md-8 text-left">{{ user.email }}div>
div>
<div class="row">
<div class="col-md-4 text-right"><span>电话:span>div>
<div class="col-md-8 text-left">{{ userprofile.phone }}div>
div>
<div class="row">
<div class="col-md-4 text-right"><span>公司:span>div>
<div class="col-md-8 text-left">{{ userinfo.company }}div>
div>
<div class="row">
<div class="col-md-4 text-right"><span>职业:span>div>
<div class="col-md-8 text-left">{{ userinfo.profession }}div>
div>
<div class="row">
<div class="col-md-4 text-right"><span>个人介绍:span>div>
<div class="col-md-8 text-left">{{ userinfo.aboutme }}div>
div>
<a href="{% url 'account:editme' %}">
<button class="btn btn-primary btn-lg">edit my informationbutton>
a>
div>
<div class="col-md-6">
<div style="margin-right: 100px">
{% if userinfo.photo %}
<img src="{{ userinfo.photo | striptags }}" alt="" class="img-circle" id="my_photo">
{% else %}
<img src="{% static 'images/avatar.png' %}" alt="">
{% endif %}
div>
<div style="margin-right:100px">
<button class="btn btn-primary btn-lg" id="upload_image" onclick="upload_image_layer()">上传头像button>
div>
div>
div>
div>
<script src="{% static 'js/jquery-3.4.1.min.js' %}">script>
<script src="{% static 'js/layer.js' %}">script>
<script>
function upload_image_layer() {
layer.open({
title: '上传头像',
area: ['600px', '600px'],
type: 2,
content: '{% url "account:my_image" %}',
})
}
script>
{% endblock %}
说明:
1).引入jquery.js
和layer.js
。
2).增加了弹出层js
部分。
3).layer
弹出层的使用请参考官网文档:https://www.layui.com/doc/modules/layer.html
此时,当点击”上传头像“时,会有一个弹出层,
不足之处是,点击”ok“后,会在这个弹出层显示个人信息,显然不是我们想要的,进入下一个步骤。
Step5
:编辑文件myproject/templates/account/imagecrop.html
{% load staticfiles %}
<link rel="stylesheet" href="{% static 'css/imagecrop.css' %}" type="text/css" />
<div class="container">
<div class="imageBox">
<div class="thumbBox">div>
<div class="spinner" style="display: none">div>
div>
<div class="action">
<div class="new-contentarea tc"> <a href="javascript:void(0)" class="upload-img">
<label for="upload-file">请先选择图片...label>
a>
<input type="file" class="" name="upload-file" id="upload-file" />
div>
<input type="button" id="btnCrop" class="Btnsty_peyton" value="OK">
<input type="button" id="btnZoomIn" class="Btnsty_peyton" value="+" >
<input type="button" id="btnZoomOut" class="Btnsty_peyton" value="-" >
div>
<div class="cropped">div>
div>
<script type="text/javascript" src="{% static 'js/jquery-1.11.1.min.js' %}">script>
<script type="text/javascript" src="{% static 'js/cropbox-min.js' %}">script>
<script type="text/javascript" src="{% static 'js/csrf.js' %}">script>
<script type="text/javascript">
$(window).load(function() {
//$('#btnCrop').click();$("#idName").css("cssText","background-color:red!important");
//$(".imageBox").css("cssText","background-position:88px 88px!important");$(".imageBox").css("cssText","background-size:222px 222px!important");
var options =
{
thumbBox: '.thumbBox',
spinner: '.spinner',
imgSrc: ''
}
var cropper = $('.imageBox').cropbox(options);
var img="";
$('#upload-file').on('change', function(){
var reader = new FileReader();
reader.onload = function(e) {
options.imgSrc = e.target.result;
cropper = $('.imageBox').cropbox(options);
getImg();
}
reader.readAsDataURL(this.files[0]);
this.files = [];
//getImg();
})
$('#btnCrop').on('click', function(){
//alert("图片上传喽");
$.ajax({
url: '{% url "account:my_image" %}',
type: 'POST',
data: {'img': img},
success: function(e) {
//location.href="{% url 'account:aboutme' %}"
if (e == '1') {
parent.location.reload()
} else {
alert('图片上传失败')
}
}
}, 'JSON')
})
function getImg(){
img = cropper.getDataURL();
$('.cropped').html('');
$('.cropped').append('+img+'" align="absmiddle" style="width:180px;margin-top:4px;border-radius:180px;box-shadow:0px 0px 12px #7E7E7E;">180px*180px
');
$('.cropped').append('+img+'" align="absmiddle" style="width:128px;margin-top:4px;border-radius:128px;box-shadow:0px 0px 12px #7E7E7E;">128px*128px
');
$('.cropped').append('+img+'" align="absmiddle" style="width:64px;margin-top:4px;border-radius:64px;box-shadow:0px 0px 12px #7E7E7E;" >64px*64px
');
}
$(".imageBox").on("mouseup",function(){
getImg();
});
$('#btnZoomIn').on('click', function(){
cropper.zoomIn();
})
$('#btnZoomOut').on('click', function(){
cropper.zoomOut();
})
});
script>
body>
html>
说明:
修改了ajax
里上传图片成功后里的函数。parent.location.reload()
表示重新加载弹出层的父页面,此时弹出层关闭。
AJAX
:js
插件能够帮助我们解决很多前端的问题,使我们操作起来更便捷,web
开发中的后端和前端,我们会经常使用类似这样的插件来实现某些功能。