Django學習——ajax發送其他請求、上傳文件(ajax和form兩種方式)、ajax上傳json格式、 Django內置序列化(了解)、分頁器的使用

1 ajax發送其他請求

1 寫在form表單 submit和button會觸發提交  <form action=""> </form>  注釋
2 使用input 類型為 button  <input type="button" id="id_btn" value="提交">

1 大坑
	-如果在form表單中,寫button和input是submit類型,會觸發form表單的提交
	-如果不想觸發:
    	-不寫在form表單中
       -使用input,類型是button
    
<form action="">
    <p>用戶名:<input type="text" id="id_name"></p>
    <p>密碼:<input type="password" id="id_password"></p>
{#    <button id="id_btn">提交</button>#}
    <input type="button" id="id_btn" value="提交">
</form>
    
// 登錄成功,重定向百度,前端重定向
location.href='//www.baidu.com'
location.href='/index/'
    
    
2 坑
	-後端響應格式如果是:html/text格式,ajax接收到數據後需要自己轉成對象
    res = JSON.parse(data)  // 不是json格式需要手動解析
	-後端響應格式是:json,ajax接收到數據後會自動轉成對象
   -總結:後端返回數據,統一都用JsonResponse
    
3 坑
    -如果使用了ajax,後端就不要返回rediret,render,HttpResponse
    -直接返回JsonResponse

2 上傳文件(ajax和form兩種方式)

默認請求編碼格斯為:urlencoded 上傳文件需要使用格式:enctype="multipart/form-data"
1 http --post--請求,有編碼格式,主流有三種
	-urlencode:默認的  ----> 從request.POST取提交的數據
	-form-data:上傳文件的  ----> 從request.POST取提交的數據,request.FILES中取文件
	-json:ajax發送json格式數據  ----> 從request.POST取不出數據
    
2 使用ajax和form表單,默認都是urlencode格式
3 如果上傳文件:form表單格式  enctype=
4 如果編碼方式是urlencode格式,放到body體(請求體)中數據格式如下: ajax預處理數據
	username=lqz&password=123
    
<body>
<h1>form表單上傳文件</h1>
<form action="" method="post" enctype="multipart/form-data">
    <p>用戶名:<input type="text" name="name"></p>
    <p>文件:<input type="file" name="myfile"></p>
    <input type="submit" value="提交">
</form>

<h1>ajax上傳文件</h1>
<p>用戶名:<input type="text" id="id_name"></p>
<p>文件:<input type="file" id="id_myfile"></p>
<button id="id_btn">提交</button>

</body>
<script>
    $('#id_btn').click(function (){
        // 如果ajax要上傳文件,需要藉助於一個js的formdata對象

        var formdata=new FormData()  // 實例化得到一個FormData對象
        formdata.append('name',$('#id_name').val())  // 追加了一個name對應填入的值
        // 追加文件
        var file=$('#id_myfile')[0].files[0]
        formdata.append('myfile',file)
        $.ajax({
            url: '/file_upload/',
            method: 'post',
            // 上傳文件,一定要注意如下兩行
            processData: false,  // 不預處理數據,
            contentType: false,  // 不指定編碼格式 使用FormData對象的默認編碼就是formdata格式
            data: formdata,
            success: function (data){
                console.log(data)
            }
        })
    })
</script>

$('#id_myfile')[0]  # jQuery對象轉成原生input

$('#id_myfile')[0].files  # 所有的文件

$('#id_myfile')[0].files[0]    # js中的文件對象




def file_upload(request):
    if request.method=='GET':
        return render(request,'file_upload.html')
    else:
        name = request.POST.get('name')
        myfile=request.FILES.get('myfile')
        print(type(myfile))  # 查看類型 <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
        from django.core.files.uploadedfile import InMemoryUploadedFile
        with open(myfile.name,'wb') as f:
            for line in myfile:
                f.write(line)
        return HttpResponse('上傳成功')

2.1 form表單上傳文件

2.2 ajax上傳文件

2.3 後端

2.4 路由

3 ajax上傳json格式

3.1 前端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="//cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    {#    <link href="//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">#}
    {#    <script src="//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>#}
</head>
<body>

<h1>ajax提交json格式</h1>

<p>用戶名:<input type="text" id="id_name"></p>
<p>密碼: <input type="password" id="id_password"></p>
<button id="id_button">提交</button>

</body>
<script>
    $('#id_button').click(function () {

        $.ajax({
            url: '/ajax_json/',
            method: 'post',
            contentType: 'application/json',  // 指定編碼格式
            data: JSON.stringify({
                name: $('#id_name').val(),
                password: $('#id_password').val()
            }),  // json格式字元串 相當於python中json.dumps
            success: function (data) {
                console.log(data)
            }
        })
    })
</script>
</html>

3.2 後端

def ajax_json(request):
    if request.method == 'GET':
       return render(request, 'ajax_json.html')
    else:
        # json格式,從POST中取不出來

        name=request.POST.get('name')
        print(type(request.POST))  # <class 'django.http.request.QueryDict'>
        # from django.http.request import QueryDict
        print(name)
        # 在body體中,b格式
        request.data = json.loads(request.body)
        name = request.data.get('name')
        password = request.data.get('password')
        print(name)
        print(password)
        return HttpResponse('ok')

4 Django內置序列化(了解)

Django內置的serializers(把對象序列化成json字元串)
from django.core import serializers
from django.core import serializers
def test(request):
    book_list = Book.objects.all()    
    ret = serializers.serialize("json", book_list)
    return HttpResponse(ret)

把對象轉成json格式字元串,Django內置的不好用,欄位不能控制
目前階段,要做序列化,for循環拼列表套字典

l = []
for user in user_list:
    l.append({'name':user.name,'password':user.password})
return JsonResponse(l,safe=False)

5 分頁器的使用

###  批量插入數據
def books_page(request):
    # 第一種方案,每循環一次,操作一下資料庫,性能低
    # for i in range(1000):
    #     book= models.Books.objects.create(name='圖書%s' % i, price=i+10, publish='東京出版社')

    # 第二種方案,批量插入
    book_list = []
    for i in range(1000):
        book = models.Books(name='圖書%s' % i, price=i+10, publish='東京出版社')
        book_list.append(book)

    models.Books.objects.bulk_create(book_list,batch_size=100)
    return HttpResponse('ok')


1 Django的分頁器(paginator)簡介
在頁面顯示分頁數據,需要用到Django分頁器組件

from django.core.paginator import Paginator

Paginator對象:    paginator = Paginator(user_list, 10)
# per_page: 每頁顯示條目數量
# count:    數據總個數
# num_pages:總頁數
# page_range:總頁數的索引範圍,如: (1,10),(1,200)
# page:     page對象    
page對象:page=paginator.page(1)
# has_next              是否有下一頁
# next_page_number      下一頁頁碼
# has_previous          是否有上一頁
# previous_page_number  上一頁頁碼
# object_list           分頁之後的數據列表
# number                當前頁
# paginator             paginator對象

from django.core.paginator import Paginator
# def books_page(request):
#     current_num = int(request.GET.get('page_num',1))  # 如果請求不到當前頁 返回第一頁
#     book_list= models.Books.objects.all()
#     paginator=Paginator(book_list,50)
#     # Paginator對象的屬性
#     print(paginator.count)  # 數據總條數
#     print(paginator.num_pages)  # 總頁數
#     print(paginator.per_page)  # 每頁顯示條目數量
#     print(paginator.page_range)  # 總頁數的索引範圍 range(1, 101)
#     # print(paginator.page(1))  # 第一頁
#     # page對象的屬性和方法
#     # has_next              是否有下一頁
#     # next_page_number      下一頁頁碼
#     # has_previous          是否有上一頁
#     # previous_page_number  上一頁頁碼
#     # object_list           分頁之後的數據列表
#     # number                當前頁
#     page = paginator.page(current_num)
#     print(page.has_next())
#     print(page.next_page_number())
#     print(page.has_previous())
#     print(page.previous_page_number())
#     print(page.object_list)
#     print(page.number)
#
#     return render(request,'book_page.html',locals())

def books_page(request):
    current_num = int(request.GET.get('page_num',1))
    book_list= models.Books.objects.all()

    paginator=Paginator(book_list,50)
    page = paginator.page(current_num)
    return render(request,'book_page.html',locals())

練習

1 使用ajax發送post請求,完成註冊功能,註冊成功,跳轉到登錄,登錄成功跳轉到百度

2 使用ajax上傳文件,保存到項目路徑的media路徑下(登錄成功才能上傳文件)

3 使用ajax上傳json格式數據,寫一個裝飾器,實現不論前端以什麼格式傳遞數據,我從視圖函數中都從request.data中取值 (POST的數據)

def json_parser(func):
    def inner(request,*args,**kwargs):
        if request.method == 'POST':
            try:
                request.data=json.loads(request.body)  # json格式
            except Exception as e:
                request.data=request.POST  # 其他兩種格式
        res = func(request,*args,**kwargs)
        return res
    return inner


@json_parser
def test_json(request):
    if request.method == 'GET':
        return render(request,'test_json.html')
    else:
        print(request.data)
        return HttpResponse('ok')

補充

json.loads(b'dfdasfda')
問題:json可以直接loads  bytes格式嗎?
	-3.5之前不可以
	-3.6以後可以

回顧

1 ajax
	$.ajax({
        url:'/test/',
        method:'get/post',
        contentType:'application/json',
        //processData:false,
        //contentType:false,
        data:json格式字元串,字典對象,formdata對象,
        success:function(){
            //data的類型取決於,後端返回時指定的響應類型
            ...
        }
    })
        
2 上傳文件(form表單,ajax)
3 提交json格式,後端無論是什麼格式
4 登錄註冊功能
Tags: