Django-Ajax、form组件
1.Ajax
1.AJAX:不是新的编程语言,而是一种使用现有标准的新方法,我们目前学习的是jQuery版本。特点:异步提交,局部刷新。
2.AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
3.基本语法
$.ajax({
url:'', // 后端地址 三种填写方式 与form标签的action一致
type:'post', // 请求方式 默认也是get
data:{'v1':v1Val, 'v2':v2Val}, // 发送的数据
success:function (args) { // 后端返回结果之后自动触发 args接收后端返回的数据
$('#d3').val(args)
}
})
"""
作业:设置一个注册小程序,用户名不能为jason并且密码不能为123或123456,不能用户点击提交就应该显示:
思路:jQuery事件,ajax事件
register.html:
<body>
<form action="" method="post">
<p>username:
<input type="text" id="i1" name="username">
<span id="s1" style="color: red"></span>
</p>
<p>password:
<input type="text" id="i2" name="password">
<span id="s2" style="color: red"></span>
</p>
<input type="submit" id="i3">
</form>
<script>
$('#i1').blur(function () {
$.ajax({
url:'',
type:'post',
data: {'i1':$('#i1').val()},
success:function (args) {
$('#s1').text(args)
}
})
})
$('#i2').blur(function () {
$.ajax({
url:'',
type: 'post',
data:{'i2':$('#i2').val()},
success:function (args) {
$('#s2').text(args)
}
})
})
</script>
</body>
views.py:
def register(request):
if request.method == 'POST':
username = request.POST.get('i1')
password = request.POST.get('i2')
if username:
if username == 'jason':
return HttpResponse('用户名不能为jason')
else:
return HttpResponse('')
if password:
if password == '123' or password == '123456':
return HttpResponse('密码过于简单,请重新输入')
else:
return HttpResponse('')
return render(request, 'register.html')
urls.py:
urlpatterns = [
path('register/',views.register)
]
作业2:在前端编写三个输入框,前两个输入框让用户输入数字,点击按钮之后第三个输入框自动返回两数之和:
views.py:
def index(request):
if request.method == 'POST':
i1 = request.POST.get('i1')
i2 = request.POST.get('i2')
i3 = int(i1) + int(i2)
return HttpResponse(i3)
return render(request,'index.html')
index.html:
<body>
<input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3">
<input type="submit" value="点我发送ajax请求" id="sub">
<script>
$('#sub').click(function () {
$.ajax({
url:'',
type:'post',
data:{
'i1':$('#i1').val(),
'i2':$('#i2').val()
},
success:function (args) {
$('#i3').val(args)
}
})
})
</script>
</body>
作业3:编写一个可以实时校验用户名的输入框,如果用户名为jason,用户色自提提示。 不能点击或者失焦才实现:
# input实时监听事件,ajax时间
register.html:
<body>
<p>username:
<input type="text" name="username" id="username">
<span style="color: red" id="s1"></span>
</p>
<p>password:
<input type="password" name="password" id="password">
<span style="color: red" ></span>
</p>
<script>
$('#username').on('input',function () {
$.ajax({
url:'',
type:'post',
data:{'i1':$('#username').val()},
success:function (args) {
$('#s1').text(args)
}
})
})
</script>
</body>
views.py:
def register(request):
if request.method == 'POST':
username = request.POST.get('i1')
if username:
if username == 'jason':
return HttpResponse('用户名不能为jason')
else:
return HttpResponse('')
return HttpResponse('')
return render(request,'register.html')
"""

2.Content-Type
1.urlencoded
ajax默认的编码格式、form表单默认也是
数据格式 xxx=yyy&uuu=ooo&aaa=kkk
django后端会自动处理到request.POST中,用request.POST.get('xxx')拿到值

2.formdata
django后端针对普通的键值对还是处理到request.POST中 但是针对文件会处理到request.FILES中。
"""
系统会根据不同的content-Type来分辨有几种文件类型,需要几个request。
"""

3.application/json:发送json格式数据类型
form表单不支持 ajax可以
<script>
$('#d1').click(function () {
$.ajax({
url:'',
type:'post',
data:JSON.stringify({'name':'jason','age':18}), // 千万不要骗人家
contentType:'application/json', //要指定contentType
success:function (args) {
alert(args)
}
})
})
</script>
后端需要从request.body中获取并自己处理
"""
views.py:
import json
def jsonfunc(request):
if request.method == 'POST':
data = request.body # b'{"name":"max","age":25}'
userdict = json.loads(data) # loads自带将二进制转为十进制功能
print(userdict) # {'name': 'max', 'age': 25}
return HttpResponse('成功成功')
return render(request,'jsonfunc.html')
jsonfunc.html:
<body>
<button id="b1">点我用ajax发送json数据</button>
<script>
$('#b1').click(function () {
$.ajax({
url:'',
type:'post',
data:JSON.stringify({'name':'max','age':25}),
contentType:'application/json',
success:function (args) {
alert(args)
}
})
})
</script>
</body>
"""
3.ajax携带文件数据
<script>
$('#d3').click(function () {
// 1.先产生一个FormData对象
let myFormDataObj = new FormData();
// 2.往该对象中添加普通数据
myFormDataObj.append('name', 'jason');
myFormDataObj.append('age', 18);
// 3.往该对象中添加文件数据
myFormDataObj.append('file', $('#d2')[0].files[0])
// 4.发送ajax请求
$.ajax({
url:'',
type:'post',
data:myFormDataObj,
// ajax发送文件固定的两个配置
contentType:false,
processData:false,
success:function (args){
alert(args)
}
})
})
</script>
"""
getfile.html:
<body>
<input type="file" id="i1">
<input value="通过ajax发送文件" id="i2">
<script>
$('#i2').click(function () {
let myFormDataObj = new FormData();
myFormDataObj.append('name','max');
myFormDataObj.append('age',18);
myFormDataObj.append('file',$('#i1')[0].files[0])
$.ajax({
url:'',
type:'post',
data:myFormDataObj,
contentType:false,
processData:false,
success:function (args) {
alert(args)
}
})
})
</script>
</body>
views.py:
def getfile(request):
if request.method == 'POST':
print(request.POST) # <QueryDict: {'name': ['max'], 'age': ['18']}>
print(request.FILES) # <MultiValueDict: {'file': [<TemporaryUploadedFile: Capture001.png (image/png)>]}>
return HttpResponse('成功')
return render(request,'getfile.html')
"""
4.ajax补充说明
1.后端print(request.isajax)可以判断当前请求是否由ajax发出。
2.后端返回的三板斧都会被args接收不再影响整个浏览器页面:
返回一个页面被args接收,同理,返回字典根本就不会被接收:


3.选择使用ajax做前后端交互时,后端一般返回的都是json格式的字典数据,当我们从前端打印出来时发现它是一个字符类型,这也就意味着它不能通过点的方式取值:
views.py:
def ajax1(request):
if request.is_ajax():
userdict = {'code':10000 ,'name':'max', 'age':25}
import json
user_data = json.dumps(userdict)
return HttpResponse(user_data)
return render(request,'ajax1.html')
ajax1.html:
<body>
<button id="d1">发送ajax请求</button>
<script>
$('#d1').click(function () { # 点击一次就发送一个ajax请求
$.ajax({
url: '',
type: 'post',
data: {'name':'max'},
success:function (args) {
console.log(args)
console.log(typeof args)
}
})
})
</script>
</body>

我们可以在$.ajax的字典中增加一个键值对:dataType:'json',这样前端就可以自动将字符串反序列化称为自定义对象。
views.py:
def ajax1(request):
if request.is_ajax():
userdict = {'code':10000 ,'name':'max', 'age':25}
import json
userdata = json.dumps(userdict)
return HttpResponse(userdata)
return render(request,'ajax1.html')
ajax1.html:
<body>
<button id="d1">发送ajax请求</button>
<script>
$('#d1').click(function () {
$.ajax({
url: '',
type: 'post',
data: {'name':'max'},
dataType:'json',
success:function (args) {
console.log(args)
console.log(typeof args)
console.log(args.name)
}
})
})
</script>
</body>
4.此外还有一种方式:我们在后端用JsonResponse模块发送字典,在前端本身就是一个自定义对象,可以直接通过点的方式取值。
views.py:
def ajax1(request):
if request.is_ajax():
userdict = {'code':10000 ,'name':'max', 'age':25}
from django.http import JsonResponse
return JsonResponse(userdict)
return render(request,'ajax1.html')
ajax1.html:
<body>
<button id="d1">发送ajax请求</button>
<script>
$('#d1').click(function () {
$.ajax({
url: '',
type: 'post',
data: {'name':'max'},
success:function (args) {
console.log(args)
console.log(typeof args)
console.log(args.name)
}
})
})
</script>
</body>

5.多对多三种创建方式
1.全自动创建(需要创建外键字段,系统会根据外键自动创建第三张表):
class Book(models,Model):
title = models.CharField(max_length=32)
authors = models.ManyToManyField(to='Author')
class Author(models.Model):
name = models.CharField(max_length=32)
'''
优势:自动创建第三张表,并且提供了add,remove,set,clear四种操作发方法。
劣势:字段固定,没办法扩展更多的字段
'''
2.纯手动创建(不需要创建外键,第三张表自己创建,可以扩展更多字段):
class Book(models.Model):
title = models.CharField(max_length=32)
class Author(models.Model):
name = models.CharField(max_length=32)
class Book2Author(models.Model):
book = models.ForeignKey(to='Book')
author = models.ForeignKey(to='Author')
others = models.CharField(max_length=32)
join_time = models.DateField(auto_now_add=True)
优势:第三张表完全由自己创建 扩展性强
劣势:编写繁琐 并且不再支持add、remove、set、clear以及正反向概念
'''没有外键,意味着第三幢表的关系需要自己添加,并且不好判断是正向还是反向查询'''
3.半自动创建():
class Book(models.Model):
title = models.CharField(max_length=32)
authors = models.ManyToManyField(to='Author',
through='Book2Author', through_fields=('book','author')
)
class Author(models.Model):
name = models.CharField(max_length=32)
class Book2Author(models.Model):
book = models.ForeignKey(to='Book', on_delete=models.CASCADE)
author = models.ForeignKey(to='Author', on_delete=models.CASCADE)
others = models.CharField(max_length=32)
join_time = models.DateField(auto_now_add=True)
优势:第三张表完全由自己创建,扩展性强 正反向概念依然清晰可用
劣势:编写繁琐不再支持add、remove、set、clear
6.django自带的序列化组件
1.前后端分离的项目,只需要返回json格式的数据即可。
将所有的书籍信息放在一个大字典内,然后返回给前端:
def ajax2(request):
book_queryset = models.Book.objects.all()
data_dict = {}
for book_obj in book_queryset:
tem_dict = {}
tem_dict['pk'] = book_obj.pk
tem_dict['title'] = book_obj.title
tem_dict['price'] = book_obj.price
tem_dict['info'] = book_obj.info
data_dict[book_obj.pk] = tem_dict
return JsonResponse(data_dict, json_dumps_params={'ensure_ascii':False})
2.上述结果我们可以直接用序列化组件serializers实现,serializers可以直接将queryset转成json格式发给前端并且前端还拥有自定义对象的特性。
def ajax2(request):
book_queryset = models.Book.objects.all()
from django.core import serializers
res = serializers.serialize('json', book_queryset)
return HttpResponse(res)
"""
但是拿到的结果是编码过后的结果,需要在BEJSON中查看解码之后的结果
"""
7.批量操作数据
1.如果想在一张表中插入100000条数据,我们的思路如下:
views.py:
def ajax4(request):
for i in range(1,10000)
models.Book.objects.create(title='第%s本书'%i,info='很带劲',price=888.88)
book_queryset = models.Book.objects.all()
return render(request,'ajax4.html',locals())
html.py:
<body>
<p>
{% for book_obj in book_queryset %}
{{ book_obj.title }}
{% endfor %}
</p>
</body>
2.如果添加的数据很多,并且数据之间有规律,我们可以采用bulk_create插入:
views.py:
def ajax5(request):
book_obj_list = [] # 1.首先生成一个空列表
for i in range(100000):
book_obj = models.Users(name='max',country='china')
book_obj_list.append(book_obj) # 2.生成100000个空对象并且添加到列表中
models.Users.objects.bulk_create(book_obj_list) # 3.直接将列表当做参数传入表中
return HttpResponse('数据传输中...')
8.自定义分页器模块
"""
分页器代码流程推导参考:
https://www.cnblogs.com/Dominic-Ji/articles/12035722.html
"""
自定义分页器代码封装:
1.在应用下新建一个目录utils,在该目录下新建一个py文件,命名为:myPage.py:
class Pagination(object):
def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
"""
封装分页相关数据
:param current_page: 当前页
:param all_count: 数据库中的数据总条数
:param per_page_num: 每页显示的数据条数
:param pager_count: 最多显示的页码个数
"""
try:
current_page = int(current_page)
except Exception as e:
current_page = 1
if current_page < 1:
current_page = 1
self.current_page = current_page
self.all_count = all_count
self.per_page_num = per_page_num
# 总页码
all_pager, tmp = divmod(all_count, per_page_num)
if tmp:
all_pager += 1
self.all_pager = all_pager
self.pager_count = pager_count
self.pager_count_half = int((pager_count - 1) / 2)
@property
def start(self):
return (self.current_page - 1) * self.per_page_num
@property
def end(self):
return self.current_page * self.per_page_num
def page_html(self):
# 如果总页码 < 11个:
if self.all_pager <= self.pager_count:
pager_start = 1
pager_end = self.all_pager + 1
# 总页码 > 11
else:
# 当前页如果<=页面上最多显示11/2个页码
if self.current_page <= self.pager_count_half:
pager_start = 1
pager_end = self.pager_count + 1
# 当前页大于5
else:
# 页码翻到最后
if (self.current_page + self.pager_count_half) > self.all_pager:
pager_end = self.all_pager + 1
pager_start = self.all_pager - self.pager_count + 1
else:
pager_start = self.current_page - self.pager_count_half
pager_end = self.current_page + self.pager_count_half + 1
page_html_list = []
# 添加前面的nav和ul标签
page_html_list.append('''
<nav aria-label='Page navigation>'
<ul class='pagination'>
''')
first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
page_html_list.append(first_page)
if self.current_page <= 1:
prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
else:
prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)
page_html_list.append(prev_page)
for i in range(pager_start, pager_end):
if i == self.current_page:
temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
else:
temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
page_html_list.append(temp)
if self.current_page >= self.all_pager:
next_page = '<li class="disabled"><a href="#">下一页</a></li>'
else:
next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
page_html_list.append(next_page)
last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
page_html_list.append(last_page)
# 尾部添加标签
page_html_list.append('''
</nav>
</ul>
''')
return ''.join(page_html_list)
2.views.py:
def page(request):
friend_queryset = models.Friend.objects.all()
from app01.utils.myPage import Pagination
current_page = request.GET.get('page')
'''可以在这里设置每页展业数据条数,页数'''
page_obj = Pagination(current_page=current_page,all_count=friend_queryset.count(),per_page_num=20,pager_count=7)
page_queryset = friend_queryset[page_obj.start:page_obj.end]
return render(request,'page.html',locals())
page.html:
{% for friend_obj in page_queryset %}
<p style="text-align: center">{{ friend_obj.name }}</p>
{% endfor %}
<div class="text-center">{{ page_obj.page_html|safe }}</div>
</body>

Django-Ajax、form组件的更多相关文章
- 〖Python〗-- Django的Form组件
[Django的Form组件] Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 Form类的使 ...
- django 使用form组件提交数据之form表单提交
django的form组件可以减少后台在进行一些重复性的验证工作,极大降低开发效率. 最近遇到一个问题: 当使用form表单提交数据后,如果数据格式不符合后台定义的规则,需要重新在前端页面填写数据. ...
- Django之Form组件
Django之Form组件 本节内容 基本使用 form中字段和插件 自定义验证规则 动态加载数据到form中 1. 基本使用 django中的Form组件有以下几个功能: 生成HTML标签 验证用户 ...
- Python之路【第二十一篇】:Django之Form组件
Django之Form组件 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试牛刀 1. ...
- 第十一篇:web之Django之Form组件
Django之Form组件 Django之Form组件 本节内容 基本使用 form中字段和插件 自定义验证规则 动态加载数据到form中 1. 基本使用 django中的Form组件有以下几个功 ...
- python Django之Form组件
python Django之Form组件 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试 ...
- Django之Form组件(一)
Django之Form组件(一) Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 基本操作:字 ...
- python框架之Django(10)-Form组件
介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来.与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否输入,输入 ...
- Django之Form组件验证
今天来谈谈Django的Form组件操作 Django中的Form一般有两种功能: ·输入html ·验证用户输入 Form验证流程 ·定义规则(是一个类) ·前端把数据提交过来 ·匹配规则 · ...
- web之Django之Form组件
Django之Form组件 本节内容 基本使用 form中字段和插件 自定义验证规则 动态加载数据到form中 1. 基本使用 django中的Form组件有以下几个功能: 生成HTML标签 验证用户 ...
随机推荐
- 使用SunnyUI的datagridview常用代码(个人常用)
1.窗体加载时初始化grid private void LayOut() { dgv.Font = new System.Drawing.Font("微软雅黑", 9F); dgv ...
- Python模块大全之《 os模块》
️前言: os 模块提供了非常丰富的方法用来处理文件和目录.是Python基础必备的,所以我用了6000字详细讲述了绝大部分os模块提供的方法,方法如下 方法一.os.makedirs()和os.re ...
- warning: ‘setAxisX‘ is deprecated
解决 将 chart->setAxisX(valueAxisX,lineSeries); 改为: chart->addSeries(lineSeries); chart->creat ...
- 【每日一题】【遍历orSet】2022年2月1日-NC66 两个链表的第一个公共结点
描述输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空.(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的) 输入描述:输入分为是3段,第 ...
- 【面试题总结】Java并发-多线程、JUC详述(思维导图)
〇.整体目录 一.多线程 1.实现方式 2.内存图 3.线程状态 4.实现线程同步 5.并发编程 二.JUC 1.概述与volatile关键字 2.ThreadLocal类 3.CAS方法 4.ato ...
- jjava基础语法
java基础语法1 注释 注意: SDK要选择JDK1.8,且下面的语言要选择8,配置完这个环境后,JAVA才能正常运行. 单行注释 //+text 快捷键:ctrl+/ 多行注释 /*+text+ ...
- sql周报
数据库分类 1.关系型数据库 Mysql Qracle MariaDB PostgreSQL mysql:开源免费 使用最广 性价比最高 Oracle:收费 但安全性高 PostgreSQL:开源免费 ...
- 电脑无法自动获取ip地址
1.按下win+r,输入cmd,打开命令提示符;2.执行ipconfig命令看下能否获取到ip地址:3.若不能,执行ipconfig /renew命令重新获取ip:4.执行ipconfig命令看下能否 ...
- 微信小程序地区和location_id对应关系
点击查看代码 location_list = [ {'location_id': '101010100', 'location_name': ['北京', '北京', '北京']}, {'locati ...
- uniapp微信小程序 下拉刷新(上拉请求下一页数据)
<template>标签中: <view class="" v-if="daShow==1"> <view class=" ...