Django中的choice字段
应用的场景:
用户信息举列:如用户性别、婚否、学历、工作状态等可以列举出来供选择的信息
书写models创建表模型:
数据的获取和查询:
总结:
""" 1 存choice里面罗列的数字与中文对应关系 print(user_obj.get_gender_display()) 只要是choices字段 在获取数字对应的数据 固定语法 get_choices字段名_display() 2 存没有罗列出来的数字 不会报错 还是展示数字 """
MTV和MVC框架 (了解概念)
MVC(Model View Controller 模型-视图-控制器)
MTV(Model Templates View 模型-模板-视图):
区别:
MVC中的View的目的是「呈现哪一个数据」,而MTV的View的目的是「数据如何呈现」。
MTV:是Django框架,自己自称的
M:models模型
T:templates模板
V:views视图
MVC:目前大部分web框架的本质
M:models
V:views
C:controller 控制器(urls)
本质:MTV其实也是MVC
Django与AJAX
关键理解:异步提交,局部刷新
例如github官网的注册界面:
注册用户名时,时刻监测用户名是否存在,向后端发送请求,进行动态的校验.
目前所接触到的向后端发送请求方式:
GET/POST请求
""" 前端中的 标签 >>>>>GET请求 浏览器中输入的url搜索>>>>>GET请求 from表单 >>>>>>>>>>>>>>>GET/POST请求 AJAX》>>>>>>>>>>>>>>>>>GET/POST请求 """
AJAX简介
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
- 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
- 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
AJAX:有点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
例子:
页面上有三个input框,在前两个input框中输入数字,点击按钮 发送ajax请求,不刷新页面的情况下,第三个框中自动算出两数之和。
前端向后端发送请求需注意:改成让Django知道走POST请求
views.py
from django.shortcuts import render,reverse,HttpResponse,redirect # Create your views here. def index(request): print(request.is_ajax()) # 用来判断当前请求方式是否是ajax请求 if request.is_ajax(): if request.method == 'POST': # print(request.POST) i1 = request.POST.get('i1') i2 = request.POST.get('i2') # 后端获取的前端数据 都是字符串格式 res = int(i1) + int(i2) return HttpResponse(res) return reverse(request,'index.html')
url,py
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/',views.index), ]
index.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.slim.js">script>
head>
<body>
<input type="text" id="l1">+<input type="text" id="l2">=<input type="text" id="l3">
<button id="l3">求和button>
<script> // 绑定点击事件
$('#l3').on('click',function () {
{#alert(123)#}
// 点击按钮 朝后端发送post请求
$.ajax({
url:'', // 控制发送给谁 不写就是朝当前地址提交
type:'post', // 发送方式是post请求
data:{'i1':$('#l1').val(),'l2':$('#l2').val()}, // 发送的数据
success:function (data) { // data形参用来接收异步提交的结果
// 将后端计算好的结果 通过DOM操作 渲染到第三个input框中
$('#l3').val(data)
}
})
})
script>
body>
html>
前端书写AJAX部分
运行的结果是:点击求和后向后端发送POST请求,取到结果并展示
contentType前后端传输数据编码格式
常用的数据编码格式有三类:
1.urlencoded >>>>> 数据格式:name=jack&pwd=123&boby=running
2.formdata >>>>>>>>> 传文件也支持传普通的键值对:name=jack&pwd=123&boby=running
3.json >>>>>>>> josn格式数据(from表单是无法发送Json格式的数据的)
form 表单:默认使用的编码格式是urlencoded,数据格式是:name=jason&pwd=123;发送到后端,
django后端针对urlencoded编码格式的数据会自动解析并放到request.POST中供用户获取。
可以修改为formdata 传文件
django后端针对只要是符合urlencoded编码格式的数据(name=jason&pwd=123)都会自动解析并放到request.POST中供用户获取
如果是文件 只要你指定的编码是formdata 就会自动解析并放到request.FILES中
ajax提交数据:提交的方式默认也是urlencoded
django后端针对不同的编码格式是如何处理的?
1、只要是符合urlencoded编码格式 都会被后端自动获取并解析放到request.POST中 2、如果是符合formdata那么文件会自动被解析放到request.FILES中 3、如果是json格式 后端默认不解析 以二进制的形式就放在request.body你可以自己手动处理即可
ajax发送json格式数据
<script> $('#b1').on('click',function () { alert(123) // 点击按钮 朝后端发送post请求 $.ajax({ url:'', // 控制发送给谁 不写就是朝当前地址提交 type:'post', // 发送方式是post请求 data:JSON.stringify({'username':'jason','password':123}), // 发送的数据 contentType:'application/json', // 告诉后端你这次的数据是json格式 success:function (data) { // data形参用来接收异步提交的结果 alert(data) // 将后端计算好的结果 通过DOM操作 渲染到第三个input矿中 $('#i3').val(data) } }) // {) script>
要指定传输的数据格式统一
后端验证数据格式:
def index(request):
#验证前后端传输数据的编码格式
if request.method =='POST': print('request.POST',request.POST) print('request.FILES',request.FILES) jason_str = request.body import json # 后端 需要手动去request.body中获取json格式数据 自己处理 res = jason_str.decode('utf-8') ral_d = json.loads(res) print(ral_d) return HttpResponse('OK') return render(request,'index.html')
总结:前后端在传输数据的时候,一定要保证数据格式和你的编码保持一致性的.
通常情况下,后端针对ajax交互,都是采取字典的形式
基于AJAX传文件:
关键字formData
传文件:如何获取文件标签存储的问文件对象?固定的语法
1、先用jQuery查找到存储文件的input标签
2、将jQuery对象转成原生Javascript对象
3、利用原生Javascript对象的方法.files[0]获取到标签内部存储的文件对象
{#// ajax传输文件#}
$('#b1').on('click',function () {
// ajax传输文件 建议使用内置对象formdata
var formData = new FormData(); // 既可以传普通的键值对 也可以传文件
// 添加普通键值
formData.append('username','jason');
formData.append('password','123');
//固定的格式
formData.append('my_file',$('#d1')[0].files[0]);
$.ajax({
url:'', // 控制发送给谁 不写就是朝当前地址提交
type:'post', // 发送方式是post请求
data:formData, // 发送的数据
// ajax发送文件需要指定两个额外的参数
processData:false, // 告诉前端不要处理数据
contentType:false, // 不适用任何编码,因为formdata对象自身自带编码 django后端也能够识别formdata对象
success:function (data) { // data形参用来接收异步提交的结果
alert(data)
// 将后端计算好的结果 通过DOM操作 渲染到第三个input矿中
$('#i3').val(data)
}
})
注意固定的格式及一些参数的使用
序列化组件
Django内置的serializers
简单的解释就是前端想拿到由ORM得到数据库中里面得一个个用户对象,为了简便操作,
后端直接将实例化出来的数据对象直接发送给客户端,这时候就需要用到序列化模块。
主要是考虑Json序列化字典的数据格式,传输的数据类型比较多,也可以以K:V键值对的形式取值。
from django.core import serializers # django自带的一个小型的序列化工具 def reg(request): user_list = models.User.objects.all()
原来的数据传输: # 将所有的数据都组织成一个符合json的一个个的字典 # user_l = [] # for user_obj in user_list: # user_l.append( # json.dumps({'username':user_obj.username, # 'age':user_obj.age, # 'gender':user_obj.get_gender_display() # }) # ) res = serializers.serialize('json',user_list) # return render(request,'index.html',locals())
利用在这json在线格式转换工具:
AJAX结合sweetalert插件的应用(动态弹框)
实现以下的动态弹框提示,点击下载Bootstrap-sweetalert项目。需要导入的插件,统一放入static文件中配置到settings.py文件下.
views.py
from django.http import JsonResponse import time def userlist(request): if request.is_ajax(): time.sleep(3) """ 一般情况下 针对ajax请求 后端通常都是返回一个字典 """ back_dic = {'code':100,'msg':''} # 直接获取用户想删除的数据的id值 delete_id = request.POST.get('delete_id') # 直接利用queryset方法 批量删除 models.User.objects.filter(pk=delete_id).delete() # 要给前端ajax返回一个消息(字典) back_dic['msg'] = '真的删除了!' return JsonResponse(back_dic) user_list = models.User.objects.all() return render(request,'userlist.html',locals())
userlist.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js">script>
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'dist/sweetalert.css' %}">
<script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}">script>
<script src="{% static 'dist/sweetalert.min.js' %}">script>
<style>
div.sweet-alert h2{
padding-top: 10px;
}
style>
head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h2 class="text-center">数据展示h2>
<table class="table-striped table table-hover table-bordered">
<thead>
<tr>
<th>序号th>
<th>主键th>
<th>用户名th>
<th>年龄th>
<th>性别th>
<th>操作th>
tr>
thead>
<tbody>
{% for user in user_list %}
<tr>
<td>{{ forloop.counter }}td>
<td>{{ user.pk }}td>
<td>{{ user.username }}td>
<td>{{ user.age }}td>
<td>{{ user.get_gender_display }}td>
<td>
<button class="btn btn-primary btn-sm">编辑button>
<button class="btn btn-danger btn-sm del" user_id="{{ user.pk }}">删除button>
td>
tr>
{% endfor %}
tbody>
table>
div>
div>
div>
<script>
$('.del').click(function () {
// 获取当前标签对象
var $btnEle = $(this);
swal({
title: "你确定要删吗?",
text: "你要是删了,你就准备跑路吧!",
type: "warning",
showCancelButton: true,
confirmButtonClass: "btn-danger",
confirmButtonText: "是的,老子就要删!",
cancelButtonText: "算了,算了!",
closeOnConfirm: false,
showLoaderOnConfirm: true
},
function(){
// 朝后端发送ajax请求
$.ajax({
url:'',
type:'post',
data:{'delete_id':$btnEle.attr('user_id')},
success:function (data) { // 后端发字典过来 前端不需要你手动转 会自动帮你转换成js自定义对象
if (data.code == 100){
{#window.location.href = ''; // 不写就是条到当前页面#}
// 通过DOM操作 实时改变页面
// 将被点击的删除按钮所在的那一行直接从DOM树中删掉
$btnEle.parent().parent().remove();
swal("删掉了!", "赶紧回去收拾行李吧,准备跑路!", "success");
}else{
swal('发生了未知的错误','估计是有bug了','info')
}
}
});
});
})
script>
body>
html>
效果如下:
自定义分页器
直接拷贝代码然后导入使用即可:
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: 最多显示的页码个数 用法: queryset = model.objects.all() page_obj = Pagination(current_page,all_count) page_data = queryset[page_obj.start:page_obj.end] 获取数据用page_data而不再使用原始的queryset 获取前端分页样式用page_obj.page_html """ 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(''' ''') first_page = '首页 ' % (1) page_html_list.append(first_page) if self.current_page <= 1: prev_page = '上一页 ' else: prev_page = '上一页 ' % (self.current_page - 1,) page_html_list.append(prev_page) for i in range(pager_start, pager_end): if i == self.current_page: temp = '%s ' % (i, i,) else: temp = '%s ' % (i, i,) page_html_list.append(temp) if self.current_page >= self.all_pager: next_page = '下一页 ' else: next_page = '下一页 ' % (self.current_page + 1,) page_html_list.append(next_page) last_page = '尾页 ' % (self.all_pager,) page_html_list.append(last_page) # 尾部添加标签 page_html_list.append(''' ''') return ''.join(page_html_list)
导入使用
from app01.utils.mypage import Pagination def 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())
booklist.html
"en"> "UTF-8">Title {% load static %} "stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> "stylesheet" href="{% static 'dist/sweetalert.css' %}">class="container">class="row">class="col-md-8 col-md-offset-2"> {% for book in page_queryset %}{{ book.title }}
{% endfor %} {{ page_obj.page_html|safe }}