Ajax
Ajax
E:\pythonDemo\django项\day7_30
choices参数
class User(models.Model):
username = models.CharField(max_length=32)
age = models.IntegerField()
# 性别
gender_choice = (
(1, '男'),
(2, '女'),
(3, '其他'),
)
gender = models.IntegerField(choices=gender_choice)
score_choices = (
('A', '优秀'),
('B', '良好'),
('C', '及格'),
('D', '不及格'),
)
score = models.CharField(choices=score_choices, null=True)
"""
孩gender字段寸的还是数字 但是如果存到的数字在上面元组列举的范围内
就可以获取到元组对应的内容
"""
if __name__ == '__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'day7_30.settings')
import django
django.setup()
from app01 import models
# models.User.objects.create(username='jason', age=18,gender=1)
# models.User.objects.create(username='egon', age=45,gender=2)
# models.User.objects.create(username='tank', age=23,gender=3)
# models.User.objects.create(username='tony', age=18,gender=4)
"""
存的时候没有列举出来的数字也能存
"""
user_obj = models.User.objects.filter(pk=1).first()
# print(user_obj.gender)
# 只要是choice的字段,如果你想要获取对应信息,固定句式 get_xxx_display
print(user_obj.get_gender_display())
user_obj1 = models.User.objects.filter(pk=4).first()
print(user_obj1.get_gender_display())
"""
如果没有对应关系,,那么字段是什么展示什么,不好有其他问题
"""
多对多三种创建方式
# 全自动
利用orm自动帮我们创建第三张关系表
class Book(models.Model):
name = models.CharField(max_length=32)
authors = models.ManyToManyField(to='Author')
class Author(models.Model):
name = models.CharField(max_length=32)
"""
缺点:
第三张关系表的拓展性极差,没有办法额外添加字段
"""
# 纯手动
class Book(models.Model):
name = models.CharField(max_length=32)
class Author(models.Model):
name = models.CharField(max_length=32)
class Book2Author(models.Model):
book_id = models.ForeignKey(to='Book')
author_id = models.ForeignKey(to='Author')
"""
优点: 利于拓展
缺点: 不能使用orm提供的方法,
不建议你用该方式
"""
# 半自动
class Book(models.Model):
name = 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)
# authors = models.ManyToManyField(to='Author',
# through='Book2Author',
# through_fields=('author', 'book')
# )
"""
through_field
通过第三张表查询对应的表需要用到那个字段,就把那个字段放前面,也就是外键建立在那个表,,
就把对应的字段放到前面
半自动可以使用orm的正反向查询,,但是不能使用add, set, remove, clear方法
"""
class Book2Author(models.Model):
book = models.ForeignKey(to='Book')
author = models.ForeignKey(to='Author')
Ajax简介
"""
异步提交,局部刷新
发送请求的方式
1.浏览器输入url地址 GET
2.a标签href属性 GET
3.form表单 GET/POST
4.ajax GET/POST
"""
案例:
"""
需求:
页面上有三个input框,在前面两个框中输入数字,点击按钮,朝后端发送ajax请求,后端计算出结果,然后返回给前端,动态展示到第三个input框,整个过程页面不准刷新,也不能在前端计算
"""
<body>
<input type="text" id="d1">
<input type="text" id="d2">
<input type="text" id="d3">
<p>
<button id="btn">click me</button>
</p>
<script>
//先给按钮绑定一个点击事件
$('#btn').click(function () {
//朝后端发送ajax请求
$.ajax({
//1. 指定朝那个后端发送请求
url:'', //不写就是朝当前地址提交
//2. 请求方式
type: 'post', //不指定默认就是get
// 3. 数据
{#data:{'username':'jason', 'password': 123},#}
data:{'i1':$('#d1').val(), 'i2': $('#d2').val()},
//4 回调函数 当后端返回结果的时候,会自动触发
success:function (args) {
{#alert(args) //通过dom操作动态渲染到input框#}
{#$('#d3').val(args)#}
console.log(typeof args)
}
})
})
</script>
def ab_ajax(request):
if request.method == "POST":
# print(request.POST)
# i1= request.POST.get('i1')
# i2 = request.POST.get('i2')
# i3 = int(i1) + int(i2)
d = {'code':100, 'msg': 66}
# return HttpResponse(json.dumps(d))
return JsonResponse(d)
return render(request, 'index.html')
前后端传输数据的编码格式(contentType)
get请求因为数据在url后面 所以不研究
url?username=jason&password=123
# form表单
默认数据编码格式是urlencode
数据格式: username=egon&password=1233
django正对符合urlencode编码的数据格式 都 会自动帮你解析封装到request.POST中
如果你把编码格式改为formdata, 那么针对普通的键值对环视解析到request.POST中而将文件解析到request.FILES
form表单没有办法发送json数据格式
#ajax
默认数据编码格式也是urlencode
username=jason&age=18
django正对符合urlencode编码的数据格式 都 会自动帮你解析封装到request.POST中
前后端传输数据的三种格式
"""
urlencode
formdata
json
"""
ajax发送json数据格式
"""
前后端传输数据的时候一定要确保编码格式跟数据真正的格式是一致的
request对象方法补充
request.is_ajax()
判断当前请求是不是ajax请求
django对json的数据不做任何处理
"""
数据格式: {"username":"jason","password":19}
针对前端发来的json数据,需要你手动处理
json.loads 可以自动识别你的二进制,,内部自动把二进制先解码
<button class="btn">click me</button>
<script>
$('.btn').click(function () {
$.ajax({
url: '',
type: 'post',
data:JSON.stringify({'username': 'jason', 'password': 19}),
contentType:'application/json', // 指定编码格式
success:function (args) {
}
})
})
</script>
def ab_json(request):
if request.is_ajax():
json_bytes = request.body
print(json.loads(json_bytes)) # {'username': 'jason', 'password': 19}
return render(request, 'ab_json.html')
ajax发送文件
"""
ajax发送文件需要借助于js内置对象,formdata
"""
<p>username:<input type="text" id="d1"></p>
<p>password:<input type="text" id="d2"></p>
<p><input type="file" id="d3"></p>
<button id="d4">click me</button>
<script>
//点击按钮朝后端发送文件和字典
$('#d4').on('click', function () {
//1. 先生成一个内置对象
let formDataObj = new FormData();
// 添加普通的键值对,
formDataObj.append('username', $('#d1').val());
formDataObj.append('password', $('#d2').val());
// 添加文件对象
formDataObj.append('myfile', $('#d3')[0].files[0])
// 发送
$.ajax({
url:'',
type:'post',
data:formDataObj,
//发送ajax文件必须要指定的两个参数
contentType: false, //不需要使用任何编码 django后端会自动识别formdata对象
processData:false, //告诉你的浏览器不要对你的数据进行任何处理
success:function (args) {
}
})
})
</script>
def ajax_file(request):
if request.is_ajax():
if request.method == 'POST':
print(request.POST)
print(request.FILES)
return render(request, 'ajax_file.html')
"""
ajax发文件:
需要利用内置对象formdata
// 添加普通的键值对,
formDataObj.append('username', $('#d1').val());
formDataObj.append('password', $('#d2').val());
// 添加文件对象
formDataObj.append('myfile', $('#d3')[0].files[0])
指定参数
contentType: false, //不需要使用任何编码 django后端会自动识别formdata对象
processData:false, //告诉你的浏览器不要对你的数据进行任何处理
django后端能够直接识别到formdata对象,并且能够将内部的普通键值对自动解析并封装到request.POST中,文件数据自动解析分装到request.FIELS
"""
django自带的序列化组件
"""
需求:
在前端给我获取到用户表的所有数据,要是列表套字典
"""
class User1(models.Model):
username = models.CharField(max_length=32)
age = models.CharField(max_length=32)
gender_choice = (
(1, '男'),
(2, '女'),
(3, '其他'),
)
gender = models.IntegerField(choices=gender_choice)
def ser(request):
user_queryset = models.User1.objects.all()
# user_list = []
# for user_obj in user_queryset:
# tmp = {
# 'pk': user_obj.pk,
# 'username': user_obj.username,
# 'age': user_obj.age,
# 'gender': user_obj.get_gender_display()
# }
# user_list.append(tmp)
# return JsonResponse(user_list, safe=False)
# 序列化
res = serializers.serialize('json', user_queryset)
# 这一步会自动帮你把数据变成json格式
"""
[
{"model": "app01.user1", "pk": 1,
"fields": {"username": "jason", "age": "13", "gender": 1}
},
{"model": "app01.user1", "pk": 2,
"fields": {"username": "egon", "age": "34", "gender": 2}
},
{"model": "app01.user1", "pk": 3,
"fields": {"username": "kevin", "age": "23", "gender": 3}
},
{"model": "app01.user1", "pk": 4,
"fields": {"username": "tank", "age": "32", "gender": 4}
}
]
写接口就是利用序列化组件渲染数据,然后写成一个接口文件
"""
return HttpResponse(res)
ajax结合sweetalert
path('user/list/', views.user_list), path('user/del/', views.del_user) def del_user(request): """ 前后端在用ajax进行交互的时候 我们通常给ajax的回调函数返回一个字典格式的数据 :param request: :return: """ print(request.POST) if request.is_ajax(): if request.method == 'POST': back_dic = {'code': 1000, 'msg': ''} delete_id = request.POST.get('delete_id') time.sleep(3) models.User1.objects.filter(pk=delete_id).delete() back_dic['msg'] = '删除成功' # 我们告诉前端我们的结果 return JsonResponse(back_dic) <script> $('.del').on('click', function () { //先将当前标签对象存储起来 let currentBtn = $(this) {#alert($(this).attr('delete_id'))#} // 二次确认弹框 swal({ title: "Are you sure?", text: "You will not be able to recover this imaginary file!", type: "warning", showCancelButton: true, confirmButtonClass: "btn-danger", confirmButtonText: "Yes, delete it!", cancelButtonText: "No, cancel plx!", closeOnConfirm: false, closeOnCancel: false, showLoaderOnConfirm: true }, function (isConfirm) { if (isConfirm) { //朝后端发送ajax请求,删除数据 $.ajax({ {#url:'/user/del/' + currentBtn.attr('delete_id'),#} url:'/user/del/', //数据放请求体 type: 'post', data : {'delete_id': currentBtn.attr('delete_id')}, success:function (args) { //{'code': 1000, 'msg': ''} // 判断相应状态码 if (args.code === 1000){ swal("Deleted!", args.msg, "success"); // 删完之后刷新一下 // window.location.reload() // 2. 利用dom操作,动态刷新 currentBtn.parent().parent().remove() }else { swal('出现未知错误', 'info') } } }) } else { swal("Cancelled", "Your imaginary file is safe :)", "error"); } }); })</script>
批量插入数据
def insert_data(request): # 先给book表插入2000条数据 # for i in range(100): # models.Book.objects.create(name='第%s本书' % i) # # 并且将数据展示到前端 # book_queryset = models.Book.objects.all() # 批量插入 book_list = [] for i in range(100): book_obj = models.Book(name='第%s本书' % i) book_list.append(book_list) models.Book.objects.bulk_create(book_list) """ 当你想要批量插入数据的时候,使用的orm提供的bulk_create可以节省很多时间 """ return render(request, 'data.html', locals())
自定义分页器推导过程
# 推导分页 每页展示十条 # 想访问那一页 current_page = request.GET.get('page', 1) # 如果拿不到默认展示第一页 try: current_page = int(current_page) except Exception as e: current_page = 1 # 每页展示十条, per_page_num = 10 # 起始位置 start_page = (current_page - 1) * per_page_num # 终止位置 end_page = current_page * per_page_num # 分页 book_list = models.Book.objects.all() all_count = book_list.count() page_count, more = divmod(all_count, per_page_num) if more: page_count += 1 page_html = '' p = current_page if current_page < 6: p=6 elif current_page > 10: p = 10 for i in range(p-5, p + 6): if p == i: page_html += '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i) else: page_html += '<li><a href="?page=%s">%s</a></li>' % (i, i) book_queryset = book_list[start_page: end_page] return render(request, 'data.html', locals()){% for book_obj in book_queryset %} {{ book_obj.name }}{% endfor %}<nav aria-label="Page navigation"> <ul class="pagination"> <li> <a href="#" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> {{ page_html|safe }} <li> <a href="#" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </ul></nav>""""""
自定义分页器
"""用别人写好的代码,,健一个utils文件夹,"""# 类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) # 后端 def get_book(request): book_list = models.Book.objects.all() current_page = request.GET.get("page",1) all_count = book_list.count() page_obj = Pagination(current_page=current_page,all_count=all_count,per_page_num=10) page_queryset = book_list[page_obj.start:page_obj.end] return render(request,'booklist.html',locals())# 前端<div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> {% for book in page_queryset %} <p>{{ book.title }}</p> {% endfor %} {{ page_obj.page_html|safe }} </div> </div></div>
浙公网安备 33010602011771号