第六十一天 图书管理系统 ajax的应用

一、前几日内容回顾

对于Queryset内容的理解
print(models.Publish.objects.filter(name='南方出版社'))
print(type(models.Publish.objects.filter(name='南方出版社')))
publish_obj = models.Publish.objects.filter(name='南方出版社').first()
print(publish_obj)
print(type(models.Publish.objects.filter(name='南方出版社').first()))
print(publish_obj.book_set)  # app01.Book.None
print(type(publish_obj.book_set))
print(publish_obj.book_set.all())  # 因为一个出版社会有多本书,所以得加all()
for i in publish_obj.book_set.all():
	print(i.title)
res = models.Publish.objects.filter(name='南方出版社').values('book__title')
print(res)
for i in publish_obj.book_set.all():
	print(i.title)
res = models.Book.objects.select_related('publish')
print(res, type(res))
for obj in res:
	print(obj.publish.name)


<QuerySet [<Publish: 出版社对象:南方出版社>]>
<class 'django.db.models.query.QuerySet'>
出版社对象:南方出版社
<class 'app01.models.Publish'>
app01.Book.None
<class 'django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager'>
<QuerySet [<Book: 书籍对象:django从入门到入土爆款>, <Book: 书籍对象:python数据分析爆款>]>
django从入门到入土爆款
python数据分析爆款
<QuerySet [{'book__title': 'django从入门到入土爆款'}, {'book__title': 'python数据分析爆款'}]>
django从入门到入土爆款
python数据分析爆款
<QuerySet [<Book: 书籍对象:python从入门到入土爆款>, <Book: 书籍对象:lunix云计算爆款>, <Book: 书籍对象:django从入门到入土爆款>, <Book: 书籍对象:python数据分析爆款>, <Book: 书籍对象:Golang高并发爆款>]> <class 'django.db.models.query.QuerySet'>
书籍对象:python从入门到入土爆款
北方出版社
书籍对象:lunix云计算爆款
北方出版社
书籍对象:django从入门到入土爆款
南方出版社
书籍对象:python数据分析爆款
南方出版社
书籍对象:Golang高并发爆款
东方出版社

"""
1、个人的理解是通过models.Publish.objects查出来的对象不管后面是value还是all还是filter出来的都是Queryset
2、all还有filter出来的Queryset需要使用first或者for循环取出一个个的class,之后再对class使用.name的方法取到最终的值,all出来的始终都是Queryset套对象!!!!!!!!!!!!!!!!
3、value出来的Queryset里面是一个个的字典,字典也可以使用for之后再使用get方法进行取值
"""

二、总结归纳(具体项目内容放在django12中了)

block content
endblock
{% extends%}


urlpatterns = [
    path('admin/', admin.site.urls),
    path('bms/', include('app01.urls'))
]
# 注意这里是app01.urls才能将子目录导入


TypeError:‘module‘ object is not iterable
# 这个错误在django中是专门针对url的


thread中可以分为thead和tbody
其中tr是行的意思有几个tr就有几行,并且标题也是占用一行的


{{ book_obj.publish_time|date:'Y年m月d日'}}
搜索浏览器中的过滤器,自动转换为需要的格式


跨表查询
res = models.Book.objects.all()
for obj in res:
	print(obj.publish.name)
——————————————————————————————————
反向跨表查询
查询南方出版社出版的书籍
4.1.先拿出版社对象
publish_obj = models.Publish.objects.filter(name='南方出版社').first()
4.2.思考正反向(外键字段在书籍中,所以是反向的)
print(publish_obj.book)  # 因为是逆向查询且结果为多个所以要在后面加上_set
print(publish_obj.book_set)  # app01.Book.None
print(publish_obj.book_set.all())  # 因为一个出版社会有多本书,所以得加all()
———————————————————————————————————
并表的之后的查询  书多--出版社一
res = models.Book.objects.select_related('publish')
for obj in res:
	print(obj.publish.name)
———————————————————————————————————
普通跨表查询
book_obj = models.Book.objects.filter(pk=3).first()
print(book_obj.author)  # app01.Author.None
print(book_obj.author.all())  # 因为一本书可以对应多个作者对象,所以得用all()来进行取值
"""
输出的结果为QuerySet套字典
<QuerySet [<Author: 作者对象:jason>, <Author: 作者对象:kevin>]>
"""
———————————————————————————————————
book_queryset = models.Book.objects.select_related('publish')
{% for book_obj in book_queryset %}
	b{{ book_obj.author.all }}
基于对象的跨表查询,本来就是基于单个Query对象的
# 首先看出来的是不是单个query对象,如果不是就利用for循环变为单个
# 这里也遵循上面的规律
# html中的魔法方法会自动识别需要加all的东西,并且自动加上,所以不用自己动手加!!!!!!!!!!!!!!!!!!!!!!!!!!


author_list = request.POST.getlist('author_list')
# 注意拿前端的返回值的时候,如果数据为多个,那么必须使用getlist

二、ajax初步使用

异步提交 局部刷新
与form表单的区别可以参考码云网址的注册页手机号输入框
ajax其实就是js自带的功能 不是一门新的技术点 我们学习的是jQuery封装之后版本


普通的提交的方法都是同步提交同步刷新的
<body>
    <form action="" method="post">
        <input type="text">+<input type="text">=<input type="text">
        <input type="submit" value="计算">
    </form>
</body>
上面的代码只能是进行提交之后才能进行校验,并且提交之后自动刷新了,原来input框中的内容就没有了
利用abAjax对代码进行改进


<body>
    <input type="text" id="d1">+<input type="text" id="d2">=<input type="text" id="d3">
    <input type="submit" value="计算" id="subBtn">
    <script>
        $('#subBtn').click(function () {
            $.ajax({
                url:'',  // 等价于form表单的action参数}
                type:'post',  // 等价于form表单的method参数}
                data:{'i1':$('#d1').val(),'i2':$('#d2').val()},  // 要发送给后端的数据}
                success: function (args) {  // 形参args就是用于接收后端返回的数据}
                    $('#d3').val(args)}
            })
        })
    </script>
</body>
————————————————————————————————————————————
def ab_ajax(request):
    if request.method == 'POST':
        i1 = request.POST.get('i1')
        i2 = request.POST.get('i2')
        res = int(i1) + int(i2)
        return HttpResponse(res)
    return render(request,'abAjax.html')
"""
url:'',  // 等价于form表单的action参数}
type:'post',  // 等价于form表单的method参数}
data:{'i1':$('#d1').val(),'i2':$('#d2').val()},  // 要发送给后端的数据,字典的格式}
success: function (args) {  // 形参args就是用于接收后端返回的数据可以利用args给任意标签赋值}
记得复习异步回调以及DOM还有ROM的操作
"""


我们更进一步模仿注册页面
# 即只要光标离开i2就自动进行结果的计算
<body>
    <input type="text" id="d1">+<input type="text" id="d2">=<input type="text" id="d3">
    <script>
        $('#d2').blur(function () {
            $.ajax({
                url:'',  // 等价于form表单的action参数}
                type:'post',  // 等价于form表单的method参数}
                data:{'i1':$('#d1').val(),'i2':$('#d2').val()},  // 要发送给后端的数据}
                success: function (args) {  // 形参args就是用于接收后端返回的数据}
                    $('#d3').val(args)}
            })
        })
    </script>
</body>
—————————————————————————————————————————————
def ab_ajax(request):
    if request.method == 'POST':
        i1 = request.POST.get('i1')
        i2 = request.POST.get('i2')
        res = int(i1) + int(i2)
        return HttpResponse(res)
    return render(request,'abAjax.html')

注意事项(is_ajax()停用)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

if request.is_ajax():
已经被下面的方法替代了
if request.headers.get('x-requested-with') == 'XMLHttpRequest':
具体理解的步骤详见网页
https://www.ydisp.cn/developer/128266.html

三、ajax详解

1.基础语法
	$.ajax({
        url:'',   控制数据的提交地址
        type:'',  控制请求方式(默认get请求)
        data:{},  组织提交的数据
        success:function(形参){
                异步回调函数
        }
    })


2.数据编码格式
Content-Type
格式1:urlencoded
	数据格式: name=jason&pwd=123&hobby=read
	django后端统一处理到request.POST中
格式2:formdata
	数据格式: 无法查阅
	django后端自动将文件数据处理到request.FILES 普通数据request.POST
格式3:application/json
	数据格式: json格式
	django后端不会处理 在request.body中存储(bytes类型) 自己处理
	语法注意事项
	data: JSON.stringify({'name':'jason','pwd':123}),
	contentType:'application/json',
# 因为urlencoded 和formdata 分别是前面讲过的request.POST和request.FILES,下面我们来写request.body
<body>
<button type="submit" id="btn_1" >快点我呀</button>
<script>
    $('#btn_1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data: JSON.stringify({'name':'jason', 'pwd':123}),
            contentType:'application/json',
            success:function (args) {

            }
        })
    })
</script>
</body>
————————————————————————————————————————————————
def ab_ajax(request):
    if request.is_ajax():
        if request.method == "POST":
            print(request.POST)
            print(request.FILES)
            print(request.body)
    return render(request, 'abAjax.html')


3.ajax携带文件数据
<input type="text" id="d1">
<input type="file" id="d2">
<button id="d3">点我</button>

<script>
	$('#d3').click(function () {
        // 1.产生内置对象
        let formData = new FormData();
        // 2.添加普通数据
        formData.append('username',$('#d1').val())
        // 3.添加文件数据
        formData.append('file', $('#d2')[0].files[0])
        // 4.发送ajax请求
        $.ajax({
            url:'',
            type:'post',
            data:formData,
            contentType:false,  // 不使用任何编码
            processData:false,  // 不处理数据对象
            success:function (args) {
            }
        })
    })
</script>
——————————————————————————————————————————————————
def ab_ajax(request):
    if request.is_ajax():
        if request.method == "POST":
            print(request.POST)
            print(request.FILES)
            print(request.body)

    return render(request, 'abAjax.html')
"""
1.先自己new一个对象,需要传输的数据对着对象进行append就行了
2.$('#d2')[0].files[0] 可以理解为   $('#d2')[0]将jquery对象变为标签对象,之后从标签对象中取文件,如果只有一个文件可以直接使用files[0],如果有多个则可以使用files[0],files[1]进行取用!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3.data中直接写刚才的对象就行了
4.在ajax中设定contentType以及processData为False
"""


4.回调函数
后端跟ajax交互 不应该再返回页面 通常情况下都是返回json格式数据
一般来说使用HttpResponse,render和redirect就不使用了,想要实现redirect的效果只能在前端
<body>
<button type="submit" id="btn_1" >快点我呀</button>
<script>
    $('#btn_1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data: '',
            success:function (args) {
                alert(args)
                window.location.href = args
            }
        })
    })
</script>
</body>
——————————————————————————————————————————————
def ab_ajax(request):
    if request.headers.get('x-requested-with') == 'XMLHttpRequest':
        if request.method == "POST":
            return HttpResponse('https://www.baidu.com')
    return render(request, 'abAjax.html')
"""
利用BOM操作我们一样可以达到页面重定向的效果
window.location.href = args
"""


5.HttpResponse和JsonResponse
前端针对HttpResponse和JsonResponse返回的json格式数据处理策略不同
前者不会自动反序列化 而后者会自动反序列化
import json
def ab_ajax(request):
    if request.headers.get('x-requested-with') == 'XMLHttpRequest':
        if request.method == "POST":
            return HttpResponse(json.dumps({'name':'jason','pwd':123}))
    return render(request, 'abAjax.html')
——————————————————————————————————————————————
<body>
<button type="submit" id="btn_1" >快点我呀</button>
<script>
    $('#btn_1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data: '',
            success:function (args) {
                console.log(typeof args)
                console.log(args)
                console.log(args.name)
                let MyJson = JSON.parse(args)
                console.log(MyJson)
                console.log(args.name)
            }
        })
    })
</script>
</body>
"""
本来是利用json对数据进行序列化后传输
但是这里console.log(typeof args)的结果却是string,导致args.name是无法进行取值的
JSON.parse(args)反序列化为JS里面的自定义对象
"""

JsonResponse的自动反序列化
<body>
<button type="submit" id="btn_1" >快点我呀</button>
<script>
    $('#btn_1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data: '',
            success:function (args) {
                console.log(typeof args)
                console.log(args)

            }
        })
    })
</script>
</body>
————————————————————————————————————————————————
from django.http import JsonResponse
def ab_ajax(request):
    if request.headers.get('x-requested-with') == 'XMLHttpRequest':
        if request.method == "POST":
            return JsonResponse({'name': 'jason', 'pwd': 123})
    return render(request, 'abAjax.html')

#如果想让前者也自动反序列化可以添加一个固定的参数dataType:'JSON'
<body>
<button type="submit" id="btn_1" >快点我呀</button>
<script>
    $('#btn_1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data: '',
            dataType:'JSON'
            success:function (args) {
                console.log(typeof args)
                console.log(args)
                console.log(args.name)
            }
        })
    })
</script>
</body>
"""
dataType:'JSON'可以使得不需要再去JsonResponse
在小白必会三板斧中,HttpResponse的作用就是=返回字符串数据,所以其他数据需要进行序列化和反序列化
所以不序列化的返回值类型为string!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
"""

四、SweetAlert弹框插件

官网网址:https://sweetalert.js.org/guides/
使用方式: <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>

<a href="#" class="btn btn-danger btn-xs delBtn">删除</a>
{% block js %}
    <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
    <script>
        $('.delBtn').click(function (){
            swal({
                  title: "你真的要删除吗?",
                  text: "如果真的删了你可能需要提桶跑路",
                  icon: "warning",
                  buttons: ['取消','确认'],
                  dangerMode: true,
                })
                .then((willDelete) => {
                  if (willDelete) {
                    swal("牛逼! 数据删了 赶紧跑路!", {
                      icon: "success",
                    });
                  } else {
                    swal("你个怂货 就知道你不敢!");
                  }
                });

        })
    </script>
{% endblock %}
"""
这上面就是给按钮绑定删除的弹框
也可以在这里使用ajax进行数据操作
if (willDelete) {下面就可以写上.ajax,之后利用data传输想要删除的id的数据
这里要非常注意<a href="#" class="btn btn-danger btn-xs delBtn">删除</a>
如果写成href=""那么弹框可能只会闪一下!!!!!!!!!!!!!!!!!!!!!!!!
"""

五、序列化

def get_book():
    book_query = models.Book.objects.all()
    return HttpResponse(book_query)
我们这里想要直接返回所有的书籍数据,但是发现返回的数据不完整
def ser(request):
    #拿到用户表里面的所有的用户对象
    user_list=models.User.objects.all()
    #导入内置序列化模块
    from django.core import serializers
    #调用该模块下的方法,第一个参数是你想以什么样的方式序列化你的数据
    ret=serializers.serialize('json',user_list)
    return HttpResponse(ret)
# 上面的代码本质上是替我们干了下面的事
book_query = models.Book.objects.all()
    # 将数据全部构造成json格式 {'pk':1,'title':'书'}
    book_list = []
    for book_obj in book_query:
        temp_dict = {}
        temp_dict['pk'] = book_obj.pk
        temp_dict['title'] = book_obj.title
        temp_dict['price'] = book_obj.price
        book_list.append(temp_dict)
posted @ 2024-01-14 16:09  暧昧的花蝴蝶  阅读(24)  评论(0)    收藏  举报