Django框架第九篇--Django和Ajax、序列化組件(serializers)、自定義分頁器、模型表choice參數

Django和Ajaxcss

1、什麼是Ajaxhtml

AJAXAsynchronous Javascript And XML)翻譯成中文就是異步的JavascriptXML」。即便用Javascript語言與服務器進行異步交互,傳輸的數據爲XML(固然,傳輸的數據不僅是XML前端

AJAX 不須要任何瀏覽器插件,但須要用戶容許JavaScript在瀏覽器上執行。jquery

  • 同步交互:客戶端發出一個請求後,須要等待服務器響應結束後,才能發出第二個請求;
  • 異步交互:客戶端發出一個請求後,無需等待服務器響應結束,就能夠發出第二個請求。

2、Ajax的優勢ajax

優勢:

  • AJAX使用JavaScript技術向服務器發送異步請求;
  • AJAX請求無須刷新整個頁面;
  • 由於服務器響應內容再也不是整個頁面,而是頁面中的部份內容,因此AJAX性能高; 
  • 兩個關鍵點:1.局部刷新,2.異步請求

 3、基於jQuery實現的Ajax數據庫

1.基本語法django

// 在html script中使用
$.ajax({
    url:'/index/',   //提交數據路徑,不寫默認是當前路徑
    type:'post',    //標定ajax的請求方式
    data:{'name':'lqz','age':18},  //data後面跟的就是你提交給後端的數據 //success爲回調函數
    success:function (data) {  //data即後端給你返回的數據
        alert(data)
    }
})

2.利用ajax提交表單中的數據 (數字的相加例子)json

index.html後端

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>

</head>
<body>
<input type="text" id="i1">+<input type="text" id="i2">=<input type="text" id="i3">
<button class="btn btn-primary" id="d1" >求和</button>

<script>
  //綁定點擊事件
  $('#d1').click(function () {
      //ajax寫法
      $.ajax({
         url:'/index/' ,
          type:'post',  //設置發送方式是post請求
          //獲取兩個輸入框的值
          data:{'i1':$('#i1').val(),'i2':$('#i2').val()},  //data是提交給後端的數據
          //success回調函數
          success:function (data) {   //data是後端返回的數據
              $('#i3').val(data)
          }
      })
  })
</script>
</body>
</html>

views.py瀏覽器

def index(request):
    # print(request.is_ajax())  # 用來判斷當前請求方式是不是ajax請求
    if request.is_ajax():
        if request.method == 'POST':
            # print(request.POST)
            #i1和i2是ajax傳遞過來的data字典鍵
            i1 = request.POST.get('i1')
            i2 = request.POST.get('i2')
            # 後端獲取的前端數據 都是字符串格式
            res = int(i1) + int(i2)
            return HttpResponse(res) #返回給ajax

    return render(request,'index.html')

須要注意的

1.在設置ajax的url路徑的時候,不寫就是朝當前地址提交數據,若是你寫了要注意路徑格式,好比是這樣('/index/'2.type是設置ajax的請求方式,若是你寫的是post,views視圖就是經過request.POST.get獲取數據,若是type是get請求方式,就是經過request.GET.get獲取數據。type值爲空時,默認是get方法

4、form表單和ajax進行文件上傳

1.contentType先後端傳輸數據編碼格式

先後端傳輸數據編碼格式

  • urlencoded
  • formdata
  • json

2.form表單和ajax上傳文件區別

form表單

1.默認使用的編碼格式是urlencoded
數據格式:name = jason&pwd=123
django後端針對urlencoded編碼格式的數據會自動解析並放在request.POST中供用戶獲取。

2.能夠修改formdata傳文件
django後端針對formdata編碼格式的數據會自動解析並放在request.FILES中供用戶獲取。

注意:先後端傳輸數據的時候必定要保證數據格式和你的編碼格式是一致的

模板層

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>

</head>
<body>
<form action="" enctype="multipart/form-data" method="post">
  <input type="text" name="name" id="name">
  <input type="file" name="myfile" id="myfile">
 <input type='submit' value = 'form表單上傳文件'> //form表單上傳文件格式
   </form> <button id="btn">ajax提交文件</button> //ajax上傳文件格式,觸發下面的ajax <script> //綁定提交按鈕 $('#btn').click(function () { //上傳文件,建議使用Formdata var formdata =new FormData(); //既能夠傳普通鍵值對,也能夠傳文件 //添加普通鍵值對 formdata.append('name',$('#name').val()); //傳文件,$('#myfile')[0].files拿到的是文件列表,取第0個把具體文件拿出來 formdata.append('myfile',$('#myfile')[0].files[0]); $.ajax({ url:'', type:'post', data:formdata, processData:false, //告訴前端不要處理數據 contentType:false, //不適用任何編碼,由於formdata對象自帶編碼,django後端也可以識別formdata對象 success:function (data) { //後端返回給前端信息 alter(data) } }) }) </script> </body> </html>

視圖層

#forms表單上傳文件
def home(request):
    if request.method == 'GET':  //渲染頁面
        return render(request,'home.html')
    #獲取文件信息
    myfile = request.FILES.get('myfile')  //獲取form表單上傳的文件
    print(myfile)    //上傳文件名
    return HttpResponse('ok')


#ajax上傳文件
def home_ajax(request):
    if request.is_ajax():
        if request.method == 'POST':
            name = request.POST.get('name')
            print(name)  #input框內容
            myfile = request.FILES.get('myfile')
            print(myfile) #文件名
            print(myfile.name)  #文件名
            return HttpResponse('ok')

    return render(request,'home.html')

路由層

url(r'^home/',views.home,name='home'),   //form表單上傳文件
url(r'^home_ajax/',views.home_ajax,name='home_ajax'),  //ajax上傳文件

注意點 

1.form表單上傳文件須要指定編碼格式enctype = 'multipart/form-data'。ajax也須要設置同樣的編碼格式,而後須要建立一個Formdata對象
獲取file文件的內容都是經過request.FILES.get() 2.經過append的方法,給對象傳值,至關於設置了一個個的鍵值對。 3.必需要設置這兩個參數 processData:false contentType:false

5、基於ajax提交json格式數據

1.ajax提交數據

ajax默認數據提交方式也是urlencoded
            
ajax發送json格式數據
    django後端針對json格式的數據 並不會自動解析放到request.POST或者request.FILES裏面
    它並不會解析json格式數據 而是將它原封不動的放在request.body中了

模板層

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>

</head>
<body>
<input type="text" name="name" id="d1">
<input type="password" name="password" id="d2">
<button id="d3">ajax提交json格式數據</button>
</body>
<script>
  $('#d3').click(function () {
      var pos_data = {'name':$('#d1').val(),'password':$('#d2').val()};  //獲取input框數據
      //JSON.stringify至關於json.dumps(),轉化成json格式的字符串
      var pos = JSON.stringify(pos_data);  //轉換格式

      $.ajax({
          url:'',
          type:'post',
          data:pos,  //發送的數據
          contentType:'application/json',  //告訴後端你此次的數據是json格式
      dataType:'json', success:function (data) { alert(data) } }) })
</script> </html>

視圖層

#ajax提交json數據
def home_json(request):
    if request.method == 'POST':
        #後端 須要手動去request.body中獲取json格式數據
        print(request.body)
        import json
        bytes_str = request.body.decode('utf-8')
        print(json.loads(bytes_str))
        return HttpResponse('ok')

    return render(request,'home_json.html')

路由層

url(r'^home_json/',views.home_json,name='home_json'),

總結:

1.若是不是上傳文件,form表單input的話,就直接傳了,contentType默認是urlencoded編碼方式
2.若是是上傳文件,ajax上傳文件就是先建立一個Formdata對象,經過append,把key,value參數傳進去。注意:form表單和ajax上傳的文件都是經過request.FILES.get()獲取。
3.ajax提交json格式的數據,先創造出一個對象,把數據放在對象裏面,而後轉換成json格式的字符串,經過JSON.stringify(data),這裏的contentType必須設置爲'application/json',這樣它的數據在視圖中就能經過request.body獲取到,是二進制格式,須要轉換成字符串。
四、在前端接收到後臺json格式數據,能夠在ajax那裏寫dataType:'json',它會自動轉換成對象

6、序列化組件

from django.core import serializers  # django自帶的一個小型的序列化工具
def reg(request):
    user_list = models.User.objects.all()
    res = serializers.serialize('json',user_list)
    return render(request,'index.html',locals())
[{
                "model": "app01.user",
                "pk": 1,
                "fields": {
                    "username": "jason",
                    "age": 18,
                    "gender": 1
                }
            }, {
                "model": "app01.user",
                "pk": 2,
                "fields": {
                    "username": "tank",
                    "age": 24,
                    "gender": 3
                }
            }, {
                "model": "app01.user",
                "pk": 3,
                "fields": {
                    "username": "egon",
                    "age": 73,
                    "gender": 2
                }
            }, {
                "model": "app01.user",
                "pk": 7,
                "fields": {
                    "username": "kevin",
                    "age": 29,
                    "gender": 4
                }
        }]

7、自定義分頁器

批量插入數據  bulk_create()

for i in range(1000):
  models.Book.objects.create(title='第%s本書'%i)
上面這種方式 效率極低
            
l = []
for i in range(10000):
  l.append(models.Book(title='第%s本書'%i))
models.Book.objects.bulk_create(l)  # 批量插入數據

自定義分頁器的使用

拷貝下面分頁器代碼,放在某個py文件裏面 

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('''
                    <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)
分頁器代碼

後端代碼

from app01.utils.mypage import Pagination  //導入分頁器代碼
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())

前端代碼

{% for book in page_queryset %}
<p>{{ book.title }}</p>
{% endfor %}
{{ page_obj.page_html|safe }}

 8、模型表參數choice

好比選擇性別男女,往數據庫中填寫的是數字1,2

模型層

class User(models.Model):
    username = models.CharField(max_length=32)
    age = models.IntegerField()
    choices = (
        (1,''),(2,''),(3,'其餘')
    )
    gender = models.IntegerField(choices=choices)

視圖層

user_obj = models.User.objects.filter(pk=1).first()

print(user_obj.get_gender_display())  #男
    """
    只要是choices字段 在獲取數字對應的註釋 固定語法
    get_choices字段名_display()
    """

注意:

1 存choice裏面羅列的數字與中文對應關係
         print(user_obj.get_gender_display())
            只要是choices字段 經過數字獲取對應的漢字
         固定語法
get_choices字段名_display()
2 存沒有羅列出來的數字 不會報錯 仍是展現數字
相關文章
相關標籤/搜索