1、ajax简单介绍
浏览器向网站发送请求时 是以URL和表单的形式提交的post 或get 请求,特点是:页面刷新
除此之外,也可以基于ajax向后台发送请求(异步)
依赖jQuery
编写ajax代码
$.ajax(
{
url: "发送的地址" ,
type: "post",
data:{
n1:123,
n2:456
},
success:function(res){
}
}
)
2、在django 使用中了解的知识点
1、在django 中使用ajax发送post请求,通过下面方法免除csrf_token
from django.shortcuts import render,redirect,HttpResponse
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def task_ajax(request):
return HttpResponse('hhhh')
2、想要去数据库中获取数据时:可以是对象也可以是字典
# 对象,当前行的所有数据
row_object = models.Order.objects.filter(id=uid).first()
row_object.id
row_object.title
也可以直接获取字典
# 字典,{"id":1,"title":"xxx"}
row_dict = models.Order.objects.filter(id=uid).values("id","title").filter()
# 列表 [obj,obj,obj]
queryset = models.Order.objects.all()
# [{"id":1,"title":"xxx"},{"id":1,"title":"xxx"},{"id":1,"title":"xxx"}]
queryset = models.Order.objects.all().values("id","title")
# queryset = [(1,"xx"),(2,"xx")]
queryset = models.Order.objects.all().values_list("id","title")
3、在django中有一个库可以实现json序列化,简化代码
from django.http import JsonResponse
def order_delete(request):
"""删除订单"""
uid = request.GET.get('uid')
exists = models.Order.objects.filter(id=uid).exists()
if not exists:
return JsonResponse({"status": False, "error": "数据不存在"})
models.Order.objects.filter(id=uid).delete()
return JsonResponse({"status": True})
3、示例,使用ajax 实现订单功能的增删改查
1、 定义订单表,在models.py中,定义表结构
from django.db import models
class Admin(models.Model):
username = models.CharField(verbose_name="用户名",max_length=16)
passwd = models.CharField(verbose_name="密码",max_length=64)
def __str__(self):
return self.username
class Order(models.Model):
"""订单表"""
oid = models.CharField(verbose_name='订单id',max_length=64)
title = models.CharField(verbose_name='商品名称',max_length=32)
price = models.DecimalField(verbose_name="价格",max_digits=10,decimal_places=2)
status_choice = (
(1,"待支付"),
(2,"已支付"),
)
status = models.SmallIntegerField(verbose_name='状态',choices=status_choice,default=1)
admin = models.ForeignKey(verbose_name="用户",to=Admin,on_delete=models.CASCADE)
2、定义路由,在urls.py中写接口路径
from django.urls import path
from app01.views import user,depart,pretty,admin,account,order
urlpatterns = [
path('order/list/',order.order_list),
path('order/add/',order.order_add),
path('order/delete/',order.order_delete),
path('order/detail/',order.order_detail),
path('order/edit/',order.order_edit),
]
3、实现接口函数,在order.py中实现不同功能的函数
- 列表展示 (查询)
from django.shortcuts import render
from datetime import datetime
import random
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from app01 import models
from app01.utils.bootstrap import BootStrapModelForm
from app01.utils.pagination import Pagination
class OrderModelForm(BootStrapModelForm):
class Meta:
model = models.Order
#fields = "__all__"
# 排除的字段
exclude = ['oid','admin']
#fields = ['oid','title','price']
def order_list(request):
queryset = models.Order.objects.all().order_by('-id')
page_obj = Pagination(request, queryset)
form = OrderModelForm()
context = {
"form" : form,
"queryset": page_obj.page_queryset, # 分完页的数据
"page_string": page_obj.html() # 生成页码
}
return render(request,'order_list.html',context)
这里使用到了分页的方法,分页方法如下:
"""
自定义的分页组件,以后如果想要使用这个分页组件,你需要做的如下几件事:
在视图函数 views.oy中
def pretty_list(request):
# 1、根据自己的情况去筛选自己的数据
queryset = models.PrettyNum.objects.all()
# 2、实例化分页对象
page_obj = Pagination(request,queryset)
context={
"search_data": search_data,
"queryset": page_obj.page_queryset, #分完页的数据
"page_string":page_obj.html() #生成页码
}
return render(request,'pretty_list.html',context)
在html 页面中
<nav aria-label="Page navigation">
<ul class="pagination">
{{ page_string }}
</ul>
</nav>
"""
from django.utils.safestring import mark_safe
import copy
class Pagination():
def __init__(self,request,queryset,page_size=10,page_param="page",plus=5):
"""
:param request: 请求的对象
:param queryset: 符合条件的数据(根据这个数据库给他镜像分页处理)
:param page_size: 每页显示多少条数据
:param page_param: 在URL中传递的获取分页的参数,例如 /pretty/list/?page=12
:param plus: 显示当前页的前或后几页(页码)
"""
query_dict = copy.deepcopy(request.GET)
query_dict._mutable = True
self.query_dict = query_dict
page = request.GET.get(page_param,"1")
if page.isdecimal():
page = int(page)
else:
page = 1
self.page = page
self.page_size = page_size
self.start = (page-1)* page_size
self.end = page * page_size
self.page_queryset = queryset[self.start:self.end]
total_count = queryset.count()
total_page_count,div = divmod(total_count,page_size)
if div:
total_page_count += 1
self.total_page_count = total_page_count
self.plus = plus
self.page_param = page_param
def html(self):
#计算出,显示当前页的前5页,后5页
if self.total_page_count <= 2 * self.plus + 1:
#数据库中的数据比较少,没有11页
start_page = 1
end_page = self.total_page_count
else:
# 数据库中的数据比较多,大于11页
# 当前页<5时,(小级值)
if self.page <= self.plus:
start_page = 1
end_page = 2 * self.plus + 1
else:
# 当前页大于5
#当前页 + 5 > 总页面
if (self.page + self.plus) > self.total_page_count:
start_page = self.total_page_count - 2*self.plus
end_page = self.total_page_count
else:
start_page = self.page - self.plus
end_page = self.page + self.plus
# 页码
page_str_list = []
self.query_dict.setlist(self.page_param,[1])
page_str_list.append('<li><a href="?{}">首页</a></li>'.format(self.query_dict.urlencode()))
# 上一页
if self.page > 1:
self.query_dict.setlist(self.page_param, [self.page -1])
prev = '<li><a href="?{}">上一页</a></li>'.format(self.query_dict.urlencode())
else:
self.query_dict.setlist(self.page_param, [1])
prev = '<li><a href="?{}">上一页</a></li>'.format(self.query_dict.urlencode())
page_str_list.append(prev)
#页面
for i in range(start_page,end_page + 1):
if i == self.page:
self.query_dict.setlist(self.page_param, [i])
ele = '<li class="active"><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(),i)
else:
self.query_dict.setlist(self.page_param, [i])
ele = '<li><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)
page_str_list.append(ele)
# 下一页
if self.page < self.total_page_count:
self.query_dict.setlist(self.page_param, [self.page + 1])
prev = '<li><a href="?{}">下一页</a></li>'.format(self.query_dict.urlencode())
else:
self.query_dict.setlist(self.page_param, [self.total_page_count])
prev = '<li><a href="?{}">下一页</a></li>'.format(self.query_dict.urlencode())
page_str_list.append(prev)
# 尾页
self.query_dict.setlist(self.page_param, [self.total_page_count])
page_str_list.append('<li><a href="?{}">尾页</a></li>'.format(self.query_dict.urlencode()))
search_string = """
<li>
<form style="float:left; margin-left: -1px" method="get">
<input name="page" style="position: relative;float: left;display: inline-block;width: 80px;border-radius: 0" type="text" class="form-control" placeholder="页码">
<button style="border-radius: 0" class="btn btn-default" type="submit">跳转</button>
</form>
</li>
"""
page_str_list.append(search_string)
page_string = mark_safe("".join(page_str_list))
return page_string
- 订单的创建
@csrf_exempt
def order_add(request):
"""创建订单,ajax请求"""
form = OrderModelForm(data=request.POST)
if form.is_valid():
#保存数据之前生成oid
form.instance.oid = datetime.now().strftime("%Y%m%d%H%M%S") + str(random.randint(1000,9999))
# 创建订单的用户为当前登录的用户,可以取session中获取当前登录用户的信息
form.instance.admin_id = request.session["info"]["id"]
form.save()
return JsonResponse({'status':True})
return JsonResponse({"status":False, "error": form.errors})
- 订单的删除
def order_delete(request):
"""删除订单"""
uid = request.GET.get('uid')
exists = models.Order.objects.filter(id=uid).exists()
if not exists:
return JsonResponse({"status": False, "error": "数据不存在"})
models.Order.objects.filter(id=uid).delete()
return JsonResponse({"status": True})
- 根据id 查询订单信息
def order_detail(request):
"""编辑获取当前行信息"""
uid = request.GET.get('uid')
row_dict = models.Order.objects.filter(id=uid).values("id", "title","status","price").first()
if not row_dict:
return JsonResponse({"status": False, "error": "数据不存在"})
result = {
"status": True,
"data": row_dict
}
return JsonResponse(result)
- 编辑订单
@csrf_exempt
def order_edit(request):
"""编辑订单"""
uid = request.GET.get('uid')
row_object = models.Order.objects.filter(id=uid).first()
if not row_object:
return JsonResponse({"status": False, "msg": "数据不存在"})
form = OrderModelForm(data=request.POST,instance=row_object)
if form.is_valid():
form.save()
return JsonResponse({'status': True})
return JsonResponse({"status": False, "error": form.errors})
4、前端页面的实现order_list.html
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<div>
<input id="btnAdd" type="button" class="btn btn-primary" value="新建订单1">
</div>
</div>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">新 建</h4>
</div>
<div class="modal-body">
<form id="formAdd">
<div class="clearfix">
{% for field in form %}
<div class="form-group">
<label >{{ field.label }}</label>
{{ field }}
<span class="error-msg" style="color:red">{{ field.errors.0 }}</span>
</div>
{% endfor %}
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">取 消</button>
<button id="btnSave" type="button" class="btn btn-primary">保 存</button>
</div>
</div>
</div>
</div>
<div class="container" style="margin-top: 15px" >
<div class="panel panel-default">
<div class="panel-heading"><span class="glyphicon glyphicon-list" aria-hidden="true"></span> 订单列表</div>
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>订单</th>
<th>商品</th>
<th>价格</th>
<th>状态</th>
<th>用户</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for obj in queryset %}
<tr>
<td>{{ obj.id }}</td>
<td>{{ obj.oid }}</td>
<td>{{ obj.title }}</td>
<td>{{ obj.price }}</td>
<td>{{ obj.get_status_display }}</td>
<td>{{ obj.admin.username }}</td>
<td>
<input uid="{{ obj.id }}" class="btn btn-primary btn-xs btn-edit" type="button" value="编辑">
<input uid="{{ obj.id }}" class="btn btn-danger btn-xs btn-delete" type="button" value="删除">
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<nav aria-label="Page navigation">
<ul class="pagination">
{{ page_string }}
</ul>
</nav>
</div>
<div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">删除订单</h4>
</div>
<div class="modal-body">
<span style="color: red">确定要删除吗? 删除之后数据将无法找回</span>
</div>
<div class="modal-footer">
<button id="btnConfirmDelete" type="button" class="btn btn-primary">确 认</button>
<button type="button" class="btn btn-default" data-dismiss="modal">取 消</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}
<script type="text/javascript">
var DELETE_ID;
var EDIT_ID;
$(function (){
bindBtnAddEvent();
bindBtnSaveEvent();
bindBtnDeleteEvent();
bindBtnConfirmDeleteEvent();
bindBtnEditEvent();
})
function bindBtnAddEvent() {
$("#btnAdd").click(function () {
//在新建的时候保存前将编辑的id 设置为undefined;
EDIT_ID = undefined;
//清空表单, $("#formAdd")是jquery对象, $("#formAdd")[0]是DOM对象
$("#formAdd")[0].reset()
//修改标题为新建
$("#myModalLabel").text('新建')
//点击新建按钮,显示对话框
$('#myModal').modal('show');
});
}
function bindBtnSaveEvent() {
$("#btnSave").click(function (){
//清除错误信息
$(".error-msg").empty();
if(EDIT_ID){
//编辑
doedit();
}else {
//新建
doadd();
}
});
}
function doadd(){
//向后台发送请求
$.ajax({
url: "/order/add/",
type: "post",
data: $("#formAdd").serialize(),
dataType: "JSON",
success:function (res){
if(res.status){
//alert("创建成功")
//清空表单, $("#formAdd")是jquery对象, $("#formAdd")[0]是DOM对象
$("#formAdd")[0].reset()
//关闭对话框
$('#myModal').modal('hide');
//刷新页面
location.reload();
} else {
//把错误信息显示在对话框中
$.each(res.error, function (name,errorList) {
$("#id_" + name).next().text(errorList[0]);
})
}
}
})
}
function doedit(){
//向后台发送请求
$.ajax({
url: "/order/edit/?uid=" + EDIT_ID,
type: "post",
data: $("#formAdd").serialize(),
dataType: "JSON",
success:function (res){
if(res.status){
//alert("创建成功")
//清空表单, $("#formAdd")是jquery对象, $("#formAdd")[0]是DOM对象
$("#formAdd")[0].reset()
//关闭对话框
$('#myModal').modal('hide');
//刷新页面
location.reload();
} else {
if(res.msg){
alert(res.msg)
}else {
//把错误信息显示在对话框中
$.each(res.error, function (name,errorList) {
$("#id_" + name).next().text(errorList[0]);
})
}
}
}
})
}
function bindBtnDeleteEvent(){
$(".btn-delete").click(function () {
$("#deleteModal").modal('show');
//获取当前行的id ,并赋值给全局变量
DELETE_ID = $(this).attr('uid');
});
}
function bindBtnConfirmDeleteEvent(){
$("#btnConfirmDelete").click(function (){
//点击确认按钮后,将要删除的id,发送到后台
$.ajax({
url: "/order/delete",
type: "GET",
dataType: "JSON",
data: {
uid: DELETE_ID
},
success:function (res){
if(res.status){
location.reload();
} else {
alert(res.error);
}
}
})
});
}
function bindBtnEditEvent(){
$(".btn-edit").click(function (){
//向后台发送ajax请求,获取当前行的信息
var uid = $(this).attr('uid');
EDIT_ID = uid;
$.ajax({
url: "/order/detail/",
type: "GET",
data: {
uid: uid
},
dataType: "JSON",
success: function (res){
if(res.status){
//清空表单, $("#formAdd")是jquery对象, $("#formAdd")[0]是DOM对象
$("#formAdd")[0].reset()
//修改标题为编辑
$("#myModalLabel").text('编辑')
//点击编辑按钮,显示对话框
$('#myModal').modal('show');
$.each(res.data, function (name,value){
$("#id_" + name).val(value)
})
}else {
alert(res.error);
}
}
})
});
}
</script>
{% endblock %}
页面效果如下: