一、Web开发与django的Ajax
(一)Ajax介绍–gogle公司
Ajax,异步的js和xml
普通提交:会携带整个页面进行提交,最明显的特征是需要刷新页面,页面重置。很多静态资源是不需要刷新的,刷新的时候可能阻塞整个服务。
缺点:
- 用户体验差
- 请求内容和响应内容冗余
为解决上述问题,ajax就出现了
- ajax能够发送局部的请求,页面整体不刷新,可进行局部刷新
- ajax可以发送一个异步请求,请求的过程中不会阻塞整个服务
ajax需要使用js语法编写,原生的js比较复杂,因为各种浏览器都对ajax的兼容不一致,使用js编写ajax,首先需要完成各个浏览器对js的实例创建。
我们使用jq封装过的ajax。
(二)Ajax请求
1.导包jq
2.Ajax完成一个get请求
Ajax的基本结构
<script>
$("#check_value").click(
function () {
username=$("#username").val(); // 获取用户名的值
password=$("#password").val(); // 获取密码的值
$.ajax( // 发起一个ajax请求
{ // ajax请求的数据需要放在一个对象中
url:'', // ajax请求的路径
type:'', // ajax请求的类型
data:'', // ajax请求的数据,在post请求中填写
success:function (data) { // 请求成功后执行的,data接口返回的数据
},
error:function (error) { //请求报错之后执行
}
}
);
}
)
</script>
需要两个视图
- 完成获取页面的功能
- 接收ajax提交的请求,返回响应
路由
视图
def ajax_get(request):
return render(request,'ajax_get.html')
from django.http import JsonResponse
def ajax_get_data(request):
# 查找数据库,判断是否可登录
result = {'code':10000,'content':''}
data = request.GET
username = data.get('username')
password = data.get('password')
if username=='' or password=='':
result['code'] = 10001
result['content'] = '请求参数为空'
else:
user = User.objects.filter(name=username,password=setPassword(password)).first()
if user:
result['code'] = 10000
result['content'] = '用户可登录'
else:
result['code'] = 10002
result['content'] = '用户名或密码错误'
# 返回一个json对象
return JsonResponse(result) # 默认情况下,JsonResponse的传入参数是个字典类型
# return HttpResponse('这是ajax提交数据')
模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ajaxget请求</title>
<script src="/static/js/jquery-1.8.3.min.js"></script>
</head>
<body>
<form action="">
用户名:<input id="username" type="text" name="username"><br>
密码:<input id="password" type="password" name="password"><br>
<input id="check_value" type="button" value="提交">
</form>
<script>
$("#check_value").click(
function () {
username=$("#username").val(); // 获取用户名的值
password=$("#password").val(); // 获取密码的值
url = '/ajax_get_data/?username='+username+'&password='+password;
$.ajax( // 发起一个ajax请求
{ // ajax请求的数据需要放在一个对象中
url:url, // ajax请求的路径
type:'get', // ajax请求的类型
data:'', // ajax请求的数据,在post请求中填写
success:function (data) { // 请求成功后执行的,data接口返回的数据
console.log(data);
console.log(data['content']);
},
error:function (error) { //请求报错之后执行
}
}
);
}
)
</script>
</body>
</html>
success
error
总结
ajax发送一个get请求
需要两个视图:
- 一个提供页面(处理第一个get请求)
- 返回一个有表单,有ajax请求的页面
- 另一个接收ajax请求,处理请求,返回响应
- 返回响应 JsonResponse对象
3.Ajax完成一个post请求
ajax_post请求跟get请求一样,需要两个视图。
因为是一个post请求,所以需要解决CRSF问题。
不同的地方:
- get请求拼接路径和参数 url = ‘/ajax_get_data/?username=’+username+’&password=’+password;
- get请求的type:‘get’
- post请求的路径 url=’/ajax_post_data/’;
- post请求的type:‘post’
- 需要构造数据字典,注意要将csrf加进去 ‘csrfmiddlewaretoken’:’{{ csrf_token }}’
路由
视图
def ajax_post(request):
return render(request,'ajax_post.html')
def ajax_post_data(request):
# 注册
result={'code':10000,'content':''}
username=request.POST.get('username')
password=request.POST.get('password')
if username=='' or password=='':
result['code'] = 10001
result['content'] = '请补全数据'
else:
user = User()
user.name = username
user.password = setPassword(password)
try:
user.save()
result['content'] = '注册成功'
except:
result['code'] = 10002
result['content'] = '注册失败'
return JsonResponse(result)
模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AjaxPost</title>
<script src="/static/js/jquery-1.8.3.min.js"></script>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
用户名:<input id="username" type="text" name="username"><br>
密码:<input id="password" type="password" name="password"><br>
<input id="check_value" type="button" value="提交">
</form>
<script>
$('#check_value').click(
function () {
username=$('#username').val();
password=$('#password').val();
url='/ajax_post_data/';
// 构造一个数据字典
send_data={
'username':username,
'password':password,
'csrfmiddlewaretoken':'{{ csrf_token }}'
};
$.ajax(
{
url:url,
type:"post",
data:send_data,
success:function (data) {
console.log(data)
},
error:function (error) {
console.log(error)
}
}
)
}
)
</script>
</body>
</html>
解决编码问题:
中加入ensure_ascii=False
优化–判断用户是否存在
当失去焦点时,判断用户是否存在
- 局部刷新ajax
- 提交地址(处理业务的视图)
- 视图中,获取传递过来的参数,判断用户名是否已存在于数据库表中
- 不存在,可使用
- 存在,不可使用
- 视图中,获取传递过来的参数,判断用户名是否已存在于数据库表中
- 模板拿到结果,进行渲染
路由
视图
def checkusername(request):
result={'code':10000,'content':''}
username=request.GET.get('name')
user=User.objects.filter(name=username).exists()
if user: # 存在
result['code']=10001
result['content']='用户名已存在'
else:
result['content']='该用户名可用'
return JsonResponse(result)
模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AjaxPost</title>
<script src="/static/js/jquery-1.8.3.min.js"></script>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
用户名:<input id="username" type="text" name="username"><div style="color: red" id="text"></div><br>
密码:<input id="password" type="password" name="password"><br>
<input id="check_value" type="button" value="提交">
</form>
<script>
$('#username').blur(
function () {
username = $('#username').val();
url='/checkusername/?name='+username;
$.ajax(
{
url:url ,
type:'get',
data:'',
success:function (data) {
$('#text').text(data.content)
},
error:function (error) {
$('#text').text(error)
}
}
)
}
);
$('#check_value').click(
function () {
username=$('#username').val();
password=$('#password').val();
url='/ajax_post_data/';
// 构造一个数据字典
send_data={
'username':username,
'password':password,
'csrfmiddlewaretoken':'{{ csrf_token }}'
};
$.ajax(
{
url:url,
type:"post",
data:send_data,
success:function (data) {
console.log(data);
console.log(data.content)
},
error:function (error) {
console.log(error)
}
}
)
}
)
</script>
</body>
</html>
注意:
模板进行url拼接时,使用的是url=’/checkusername/?name=’+username;
参数名为name
这时视图中获取GET请求参数时,需要使用name作为参数名获取,即username=request.GET.get(‘name’)
这两处是需要对应的
二、cookie和session
由于http请求是无状态的,无法记录身份,所以需要一种机制能够长期的记录身份,最早出现的就是cookie。
cookie:是由服务器下发给用户的,保存在用户的浏览器上,用于校验身份的数据,cookie的工作机制就像上面说的通关文牒。
-
用户第一次请求服务器
服务器验证用户的用户名,密码,下发cookie
-
用户第二次携带cookie请求服务器
服务器根据用户携带的cookie确定用户的身份
(一)cookie
优点:
根本上解决了用户持续访问的问题
缺点:
由于cookie是保存在用户本地的,所以会导致一些安全问题,cookie可以被修改,还可以被模仿
1.根据登录流程认识cookie
- 用户提供用户名,密码进行登录
- 服务器接收用户名,密码
- 验证用户名,密码
- 存在
- 校验密码
- 密码正确
- 设置cookie,下发cookie
- 登录成功,跳转到首页
- 密码错误
- 返回密码错误
- 密码正确
- 校验密码
- 不存在
- 返回用户不存在
- 存在
2.cookie的使用
首先完成用户登录,跳转到首页
视图
# 登录,重定向
from django.http import HttpResponseRedirect
def login(request):
if request.method == 'POST':
username=request.POST.get('username')
password=setPassword(request.POST.get('password'))
user = User.objects.filter(name=username,password=password).first()
if user: # 用户存在,且密码正确
# 跳转首页
return HttpResponseRedirect('/index/')
return render(request,'login.html',locals())
模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
路由
cookie的设置
修改视图
# 登录,重定向
from django.http import HttpResponseRedirect
def login(request):
if request.method == 'POST':
username=request.POST.get('username')
password=setPassword(request.POST.get('password'))
user = User.objects.filter(name=username,password=password).first()
if user: # 用户存在,且密码正确
# 跳转首页
response = HttpResponseRedirect('/index/')
response.set_cookie('name','admin')
response.set_cookie('password','123123')
return response
return render(request,'login.html',locals())
cookie设置参数
key cookie的键
value cookie的值
max_age=None cookie存在的时间,有效时间
expires=None cookie的超时时间,跟max_age 冲突,两者二选一
path=’/’ cookie起作用的范围,默认是当前网页
domain=None cookie起作用的域名
secure=False 如果为True使用https传递cookie,默认为False
httponly=False 如果为True只通过http传递cookie
samesite=None 相同的网站(域名)使用cookie
cookie的获取
利用装饰器和Cookie,实现登录拦截
编写loginVaild装饰器
# 登录拦截装饰器
def loginVaild(fun):
def inner(request,*args,**kwargs):
username=request.COOKIES.get('name')
if username:
return fun(request)
else:
return HttpResponseRedirect('/login/')
return inner
修改index视图及about视图
@loginVaild
def about(request):
return render(request,'about.html')
@loginVaild
def index(request):
article = Article.objects.order_by('-date')[:6]
recommend_article = Article.objects.filter(recommend=1)[:7]
click_article = Article.objects.order_by('-click')[:12]
return render(request,'index.html',locals())
cookie的删除
视图
# 登出,删除cookie
def logout(request):
response=HttpResponseRedirect('/login/')
response.delete_cookie('name')
return response
路由
(二)session
session就是为了解决cookie不安全问题而提出的一种会话机制。
session本身就是一种会话,值一次通信从开始到结束,只有在web开发中,session才会以会话的机制出现。
web的session是将用户的信息存在服务器上面的一种web身份校验技术。session需要结合cookie使用,需要通过cookie下发一个id(session_id),然后将用户的具体信息保存在数据库中。
cookie和session的区别
- cookie放在本地,session放在服务器上面,通常是在数据库当中
- 校验cookie速度快,但安全性不高
- 校验session速度慢,但安全性较高
1.session的操作
session的创建
session的获取
session对象在django当中以一个类字典对象出现,我们可以使用字段的方法对其进行操作。
session的删除
博客项目修改页面
项目源码
持续更新
修改文章页
视图
路由
模板
完成一个完整的登录效果
项目源码
持续更新
进入虚拟环境,创建项目,创建app子应用
配置:
- 注册子应用
- 创建templates和static目录
- 配置templates和static
- 配置数据库
创建模型
class LoginUser(models.Model):
email = models.EmailField()
password = models.CharField(max_length=32)
username = models.CharField(max_length=32,null=True,blank=True)
# null针对数据库,True表示可以为空,即在数据库的存储中可以为空
# blank 针对表单,表示在表单中该字段可以不填,但对数据库没有影响
phone_number = models.CharField(max_length=11,null=True,blank=True)
photo = models.ImageField(upload_to='images',null=True,blank=True)
age = models.IntegerField(null=True,blank=True)
gender = models.CharField(max_length=4,null=True,blank=True)
address = models.TextField(null=True,blank=True)
数据迁移
数据库配置
pycharm默认没有安装sqlite驱动
需要下载
安装缺少的驱动文件
将他们移除
再次拖入
查看数据库