Django進階(二)

Django

choice參數

choice參數
用戶性別
用戶學歷
用戶工做狀態
客戶來源
...html

choices = (
  (1,'male'),
  (2,'female'),
  (3,'others')
)
gender = models.IntegerField(choices=choices)
"""
1.若是我存的是上面元組中數字會怎麼樣
2.若是我存的數字不在元組範圍內又會怎樣
    1.數字沒有對應關係 是能夠存的
"""
from app01 import models
user_obj = models.Userinfo.objects.filter(pk=4).first()
print(user_obj.username)
print(user_obj.gender)
# 針對choices字段 若是你想要獲取數字所對應的中文 你不能直接點字段
# 固定句式   數據對象.get_字段名_display()  當沒有對應關係的時候 該句式獲取到的仍是數字
print(user_obj.get_gender_display())

實例1前端

record_choices = (('checked', "已簽到"),
                  ('vacate', "請假"),
                  ('late', "遲到"),
                  ('noshow', "缺勤"),
                  ('leave_early', "早退"),
                 )
record = models.CharField("上課紀錄", choices=record_choices, default="checked",

實例1python

score_choices = ((100, 'A+'),
                 (90, 'A'),
                 (85, 'B+'),
                 (80, 'B'),
                 (70, 'B-'),
                 (60, 'C+'),
                 (50, 'C'),
                 (40, 'C-'),
                 (0, ' D'),
                 (-1, 'N/A'),
                 (-100, 'COPY'),
                 (-1000, 'FAIL'),
                )
score = models.IntegerField("本節成績", choices=score_choices, default=-1)

MTV與MVC模型

django號稱是MTV框架,其實他仍是MVC框架
MTV:
M:models ,模型,就是數據模型,負責數據的存取;
T: templates ,模板,負責頁面的展現邏輯;
V: views ,視圖函數,負責業務邏輯的處理;
MVC:
M:models, 模型,就是數據模型,負責數據的存取;
V: views, 視圖,負責頁面的展現邏輯;
C: contronner(路由匹配), 控制器,負責業務邏輯的處理;jquery

注: 核心目的就是爲了解耦,提升開發效率ajax

ajax

AJAX(Asynchronous Javascript And XML)翻譯成中文就是「異步的Javascript和XML」。即便用Javascript語言與服務器進行異步交互,傳輸的數據爲XML(固然,傳輸的數據不僅是XML)。(我的經驗Asyn開頭,基本都是異步相關)數據庫

AJAX 不是新的編程語言,而是一種使用現有標準的新方法。django

AJAX 最大的優勢是在不從新加載整個頁面的狀況下,能夠與服務器交換數據並更新部分網頁內容。(這一特色給用戶的感覺是在不知不覺中完成請求和響應過程)編程

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

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

ajax語法結構

$.ajax({
  url:'',  # 指定朝哪一個後端地址發送請求  不寫默認朝當前地址提交
  type:'post',  # 指定提交方式
  data:{'username':'jason','password':'123'},
  success:function(data){  # data指代的就是後端返回的異步提交的結果
    # 異步回調機制邏輯處理代碼
  }
})

異步提交

同步異步:描述的任務的提交方式

​ 同步:提交任務以後 原地等待任務的返回結果 期間不幹任何事兒
​ 異步:提交任務以後 不肯地等待 直接執行下一行代碼 任務的返回經過回調機制

阻塞非阻塞:程序的運行狀態

​ 程序運行的三狀態圖

局部刷新

​ 一個頁面 不是總體刷新 而是頁面的某個地方局部刷新

Ajax是一門js的技術,基於原生js開發實現的,可是原生的js寫代碼過於繁瑣

只學習如何使用jQuery實現ajax

基本語法結構:

$.ajax({
  url:'', # 指定抄那個後端地址發送請求,不寫默認朝當前地址提交
  type:'post', # 指定提交方式
  data: {'username':'json', 'password': '123'}
  success:function(data){
    # data指代的是後端返回的異步提交的結果
    # 異步回調機制邏輯代碼處理
  }
})

什麼是 JSON ?

  • JSON 指的是 JavaScript 對象表示法(JavaScript Object Notation)
  • JSON 是輕量級的文本數據交換格式
  • JSON 獨立於語言 *
  • JSON 具備自我描述性,更易理解

  • JSON 使用 JavaScript 語法來描述數據對象,可是 JSON 仍然獨立於語言和平臺。JSON 解析器和 JSON 庫支持許多不一樣的編程語言。

合格的json對象(json只認雙引的字符串格式):

["one", "two", "three"]
{ "one": 1, "two": 2, "three": 3 }
{"names": ["張三", "李四"] }
[ { "name": "張三"}, {"name": "李四"} ] 

不合格的json對象:

{ name: "張三", 'age': 32 }  // 屬性名必須使用雙引號
[32, 64, 128, 0xFFF] // 不能使用十六進制值
{ "name": "張三", "age": undefined }  // 不能使用undefined
{ "name": "張三",
  "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
  "getName":  function() {return this.name;}  // 不能使用函數和日期對象
}

實例:

1.展現一個前端頁面 頁面上有三個輸入框 前兩個框輸入數字 點擊按鈕朝後端發請求
頁面不刷新的狀況下 完成數字的加法運算

<input type="text" id="t1"> + <input type="text" id="t2"> = <input type="text" id="t3">
<p>
<button id="b1">計算</button>
</p>

$('#b1').on('click',function () {
  // 朝後端提交post數據
  $.ajax({
    // 1.到底朝後端哪一個地址發數據
    url:'',  // 專門用來控制朝後端提交數據的地址  不寫默認就是朝當前地址提交
    // 2.到底發送什麼請求
    type:'post',  // 專門制定ajax發送的請求方式
    // 3.發送的數據究竟是什麼
    data:{'t1':$('#t1').val(),'t2':$('#t2').val()},
    // 4.異步提交的任務 須要經過回調函數來處理
    success:function (data) {  // data形參指代的就是異步提交的返回結果
                             // 經過DOM操做將內容 渲染到標籤內容上
                             $('#t3').val(data)
                            }
  })
})
from django.shortcuts import render,HttpResponse
def index(request):
  print(request.is_ajax())  # 判斷當前請求是不是ajax請求
  if request.is_ajax():
    if request.method == 'POST':
      # print(request.POST)
      t1 = request.POST.get('t1')
      t2 = request.POST.get('t2')
      res = int(t1) + int(t2)
      return HttpResponse(res)

先後端傳輸數據編碼格式

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

form表單 默認的提交數據的編碼格式是urlencoded
    urlencoded
        username=admin&password=123這種就是符合urlencoded數據格式

        django後端針對username=admin&password=123的urlencoded數據格式會自動解析
        將結果打包給request.POST 用戶只須要從request.POST便可獲取對應信息

    formdata
        django後端針對formdata格式類型數據 也會自動解析可是不會方法request.POST中而是給你放到了request.FILES中
    # form表單傳輸文件的時候  編碼格式就必須有默認的改成formdata
    ajax  ajax默認的提交數據的編碼格式也是urlencoded
    username=jason&password=123

​ 總結:django後端針對不一樣的編碼格式數據 會有不一樣的處理機制以及不一樣的獲取該數據的方法

先後端在作數據交互的時候 必定必定要代表你所發的的數據究竟是什麼格式

前段後交互 你不能騙人家
你的數據時什麼格式 你就應該準確無誤告訴別人是什麼格式

Ajax傳json格式數據

​ django後端針對json格式的數據 不會自動幫你解析 會直接原封不動的給你放到request.body中
​ 你能夠手動處理 獲取數據

1.將bytes類型轉成json格式字符串
2.利用json模塊json.loads反序列化出來

json_bytes = request.body
​ json_str = str(json_bytes,encoding='utf-8')
​ json_dict = json.loads(json_str)

​ 注意點: 先後端交互數據的時候 必定要作到數據個編碼格式的一致性,
​ 1. 指定contentType參數
​ contentType:'application/json',

2. 要將你發送的數據 確保是json格式的
            data:JSON.stringify({'username':'jason','password':'123'})
<form action="" method="post" enctype="">   # application/x-www-form-urlencoded 發普通鍵值, multipart/form-data 發文件,向普通兼容,反之不行。 
 
  <input type="text" name="username">
  <input type="password" name="password">
  <input type="file" name="myfile">
  <input type="submit">
</form>

ajax傳文件

須要利用內置對象 Formdata
    該對象既能夠傳普通的鍵值 也能夠傳文件
    
    # 獲取input獲取用戶上傳文件的文件的內容
    // 1.先經過jquery查找到該標籤
    // 2.將jquery對象轉換成原生的js對象
    // 3.利用原生js對象的方法 直接獲取文件內容
    $('#t3')[0].files[0]

​ $('#b1').click(function () {
​ // 1.先生成一個formdata對象
​ var myFormData = new FormData();
​ // 2.朝對象中添加普通的鍵值
​ myFormData.append('username',$("#t1").val());
​ myFormData.append('password',$("#t2").val());
​ // 3.朝對象中添加文件數據
​ // 1.先經過jquery查找到該標籤
​ // 2.將jquery對象轉換成原生的js對象
​ // 3.利用原生js對象的方法 直接獲取文件內容
​ myFormData.append('myfile',$('#t3')[0].files[0]);
​ $.ajax({
​ url:'',
​ type:'post',
​ data:myFormData, // 直接丟對象

// ajax傳文件 必定要指定兩個關鍵性的參數
        contentType:false,  // 不用任何編碼 由於formdata對象自帶編碼 django可以識別該對象
        processData:false,  // 告訴瀏覽器不要處理個人數據 直接發就行

        success:function (data) {
            alert(data)
        }
    })
})

「」「

ajax傳文件須要注意的事項
1.利用formdata對象 可以簡單的快速傳輸數據 (普通鍵值 + 文件)
2.有幾個參數
data:formdata對象

contentType:false
processData:false

」「」

序列化組件

自動把數據序列化

1.將用戶表的數據 查詢出來 返回給前端
給前端的是一個大字典 字典裏面的數據的一個個的字段
from django.core import serializers
def ser(request):
user_queryset = models.Userinfo.objects.all()
# [{},{},{},{}]
# user_list = []
# for user_obj in user_queryset:
#     user_list.append({
#         'username':user_obj.username,
#         'password':user_obj.password,
#         'gender':user_obj.get_gender_display(),
#     })
res = serializers.serialize('json',user_queryset)
print(res)
return render(request,'ser.html',locals())

ajax結合sweetalert聯合

ajax + sweetalert
        $("#b55").click(function () {
        swal({
                    title: "你肯定要刪除嗎?",
                    text: "刪除可就找不回來了哦!",
                    type: "warning",
                    showCancelButton: true,  // 是否顯示取消按鈕
                    confirmButtonClass: "btn-danger",  // 確認按鈕的樣式類
                    confirmButtonText: "刪除",  // 確認按鈕文本
                    cancelButtonText: "取消",  // 取消按鈕文本
                    closeOnConfirm: false,  // 點擊確認按鈕不關閉彈框
                    showLoaderOnConfirm: true  // 顯示正在刪除的動畫效果
                },
                function () {
                    var deleteId = 2;
                    $.ajax({
                        url: "/delete_book/",
                        type: "post",
                        data: {"id": deleteId},
                        success: function (data) {
                            if (data.code === 0) {
                                swal("刪除成功!", "你能夠準備跑路了!", "success");
                            } else {
                                swal("刪除失敗", "你能夠再嘗試一下!", "error")
                            }
                        }
                    })
                });
    })

批量插入數據

回顧: 列表添加元素的方式:

append : # 尾部追加

extend : # 合併

insert : #索引

關鍵詞: bulk_create

實例:新建Django,app

urls.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), # 批量導入
]

models.py

from django.db import models

# Create your models here.


class Book(models.Model):
    title = models.CharField(max_length=32)

views.py

from django.shortcuts import render
from app01 import models
# Create your views here.

# 批量插入兩種方法
def index(request):
# 1.往書籍表中插入數據 1000
for i in range(1000):  # 這種插入方式 效率極低
     models.Book.objects.create(title='第%s本書'%i)
book_list = []
    book_queryest = models.Book.objects.all()
    return render(request,'index.html', locals())
 # 1.往書籍表中插入數據 100000
for i in range(100000):  # 時間仍是很短  二者差距很大
  book_list.append(models.Book(title='第%s本書'%i))
  models.Book.objects.bulk_create(book_list)  # 批量插入數據
  # 2.將剛剛插入的數據查詢出來展現到前端
  book_queryset = models.Book.objects.all()
  return render(request,'index.html',locals())

自定義分頁器

  1. queryset : 對象支持切片取值

封裝:項目下新建文件夾utils,在該文件夾下mypage.py文件,將下列代碼複製進去

class Pagination(object):
  def __init__(self, current_page, all_count, per_page_num=10, 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)

前端文件:

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>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>
</head>
<body>
{% for book_obj in book_queryest %}
    <p>{{ book_obj.title }}</p>
{% endfor %}
<nav aria-label="Page navigation">
  <ul class="pagination">
    <li>
      <a href="#" aria-label="Previous">
        <span aria-hidden="true">&laquo;</span>
      </a>
    </li>
      {{ page_html|safe }}
{#    <li><a href="?page=1">1</a></li>#}
{#    <li><a href="?page=2">2</a></li>#}
{#    <li><a href="?page=3">3</a></li>#}
{#    <li><a href="?page=4">4</a></li>#}
{#    <li><a href="?page=5">5</a></li>#}
    <li>
      <a href="#" aria-label="Next">
        <span aria-hidden="true">&raquo;</span>
      </a>
    </li>
  </ul>
</nav>



</body>
</html>

login.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>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>

</head>
<body>
{% for book_obj in page_queryset %}
    <p>{{ book_obj.title }}</p>
{% endfor %}
{{ page_obj.page_html|safe }}
</body>
</html>

views.py

from django.shortcuts import render,HttpResponse,redirect
from app01 import models
# Create your views here.
from django.core.exceptions import  ValidationError
def index(request):
    # 1.往書籍表中插入數據 1000
    # for i in range(1000):  # 這種插入方式 效率極低
    #     models.Book.objects.create(title='第%s本書'%i)
    book_list = []
    for i in range(100000):
        book_list.append(models.Book(title='第%s本書'%i))
    models.Book.objects.bulk_create(book_list)  # 批量插入數據
    # 2.將剛剛插入的數據查詢出來展現到前端

#     # 1.獲取用戶想要訪問的頁碼數
    current_page = request.GET.get('page',1)  # 若是沒有page參數 默認就展現第一頁
#     # 轉成整型
    current_page = int(current_page)
#     # 2.每頁展現10條數據
    per_page_num = 10
#
#     # 3.定義起始位置和終止位置
    start_page = (current_page - 1) * per_page_num
    end_page = current_page * per_page_num
#
#     # 4.統計數據的總條數
    book_queryset = models.Book.objects.all()
    all_count = book_queryset.count()
#
#     # 5.求數據到底須要多少頁才能展現完
    page_num, more = divmod(all_count,per_page_num)  # divmod(100,10)
    if more:
        page_num += 1
    # page_num就以爲了 須要多少個頁碼
    page_html = ''
    xxx = current_page  # xxx就是用戶點擊的數字
    if current_page < 6:
         current_page = 6
    for i in range(current_page-5,current_page+6):
        if xxx == i:
            page_html += '<li class="active"><a href="?page=%s">%s</a></li>'%(i,i)
        else:
            page_html += '<li><a href="?page=%s">%s</a></li>' % (i, i)

    book_queryset = book_queryset[start_page:end_page]
    return render(request,'index.html',locals())

"""
分頁思路
per_page_num = 10
current_page                   start_page                      end_page
    1                              0                                10
    2                              10                               20
    3                              20                               30
    4                              30                               40

per_page_num = 5
current_page                   start_page                      end_page
    1                              0                                5
    2                              5                                10
    3                              10                               15
    4                              15                               20

start_page = (current_page - 1) * per_page_num
end_page = current_page * per_page_num
"""


from app01.utils.mypage import Pagination
# 使用封裝好的分頁器代碼
def login(request):
    book_queryset = models.Book.objects.all()
    current_page = request.GET.get('page',1)
    all_count = book_queryset.count()
    # 1.實例化產生對象
    page_obj = Pagination(current_page=current_page,all_count=all_count)
    # 2.對真實數據進行切片操做
    page_queryset = book_queryset[page_obj.start:page_obj.end]
    return render(request,'login.html',locals())

urls.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),
    url(r'^login/', views.login),
]
自定義分頁器的使用   新建一個py文件將代碼直接拷貝過去
後端
from app01.utils.mypage import Pagination
# 使用封裝好的分頁器代碼
def login(request):
  book_queryset = models.Book.objects.all()
  current_page = request.GET.get('page',1)
  all_count = book_queryset.count()
  # 1.實例化產生對象
  page_obj = Pagination(current_page=current_page,all_count=all_count)
  # 2.對真實數據進行切片操做
  page_queryset = book_queryset[page_obj.start:page_obj.end]
  return render(request,'login.html',locals())

前端

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

建立多對多表關係的三種方式

  1. 全自動(推薦使用**)
    好處在於 django orm會自動幫你建立第三張關係表
    可是它只會幫你建立兩個表的關係字段 不會再額外添加字段
    雖然方便 可是第三張表的擴展性較差 沒法隨意的添加額外的字段

class Book(models.Model):
    ...
    authors = models.ManyToManyField(to='Author')
    
    class Author(models.Models):
    ...
  1. 純手動(不推薦)

    好處在於第三張表能夠任意的添加額外的字段
    不足之處在於orm查詢的時候 不少方法都不支持 查詢的時候很是麻煩
class Book(models.Model):
...
class Author(models.Models):
...

class Book2Author(models.Model):
book_id = models.ForeignKey(to='Book')
author_id = models.ForeignKey(to='Author')
create_time = models.DateField(auto_now_add=True)
...

半自動(推薦使用******)

​ 手動建表 可是你會告訴orm 第三張表是你本身建的
​ orm只須要給我提供方便的查詢方法
​ 第三種雖然可使用orm查詢方法
​ 可是不支持使用
​ add()
​ set()
​ remove()
​ clear()

class Book(models.Model):
    ...
    authors = models.ManyToManyField(to='Author', through='Book2Author', through_fields=('book','author'))


class Author(models.Model):
    ...
    books = models.ManyToManyField(to='Book', through='Book2Author', through_fields=('author', 'book'))
    
class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')
    create_time = models.DateField(auto_now_add=True)
    ...
# 1.半自動 必定要加兩個額外的參數
    through='Book2Author', through_fields=('book','author')
# 2.後面字段的順序
    由第三張表經過哪一個字段查詢單表 就把哪一個字段放前面

"""
在設計項目的時候 必定要給本身留後路 防止後續的迭代更新 

"""

form組件

1、前提

​ 1.註冊功能
​ 用戶輸入的用戶名中 不能包含《書名》
​ 若是包含了 就提示用戶 輸入的內容不符合社會主義核心價值觀
​ 用戶輸入的密碼 不能小於三位
​ 若是密碼少於三位 提示用戶 密碼過短了

​ 校驗數據一般是先後端都有校驗
可是前端校驗無關緊要
​ 後端也必需要有校驗 反正一句話 前端可有不校驗 後端必須校驗!!!

1.搭建前端頁面 >>> 渲染頁面

<!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>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>
</head>
<body>
<form action="" method="post">
    <p>username:
        <input type="text"name="userrname">
        <span style="...">{{ back_dic.username }}</span>>
    </p>
    <p>password:<input type="text" name="username">
        <span style="...">{{ back_dic.password }}</span>
    </p>
    <input type="submit">
</form>

</body>
</html>

2.獲取前端用戶提交的數據校驗 >>> 校驗數據

def reg(request):
    back_dic = {"username":'', "password":''}
    if request.method == 'POST':
        username = request.POST.get("username")
        password = request.POST.get('password')
        if "書名" in username:
            back_dic['username'] = '不符合社會主義核心價值觀'
        if len(password) < 3:
            back_dic['password'] = '密碼不能少於三位數'
    return request(request, 'reg.html', locals())

3.對數據的校驗的結果 展現到前端頁面給用戶查看 >>> 展現錯誤信息
因書名含敏感字換爲書名

form組件可以自動幫你完成上面的三件事
1.渲染頁面
2.校驗數據
3.展現錯誤信息

form組件的使用

  1. 給本身定義一個類

views:

class MyRegForm(forms.Field):
 username = forms.CharField(min_length=3, max_length=8)
 password = forms.CharField(min_length=3, max_length=8)
 email = forms.EmailField()  # 是什麼數據類型就必須傳什麼數據類型

校驗數據

python Console:

from app01 import views
# 1.給自定義的類傳一個字典
obj = views.MyRegForm({'username':'jason','password':'12','email':'123'})
# 2.判斷數據是否所有合法
obj.is_valid()  # 只有數據所有符合要求才會是True
Out[4]: False
  # 3.查看符合校驗規則的數據
  obj.cleaned_data
  Out[5]: {'username': 'jason'}
    # 4.查看不符合條件的數據以及不符合的緣由是什麼
    obj.errors
    Out[6]: 
      {
        'password': ['Ensure this value has at least 3 characters (it has 2).'],
        'email': ['Enter a valid email address.']
      }

      # 5.校驗數據的時候 默認狀況下類裏面全部的字段都必須傳值
      obj = views.MyRegForm({'username':'jason','password':'123'})
      obj.is_valid()
      Out[12]: False
        obj.errors
        Out[13]: {'email': ['This field is required.']}
          # 6.默認狀況下能夠多傳 可是絕對不能少傳
          obj = views.MyRegForm({'username':'jason','password':'1233','email':'123@qq.com','xxx':'ooo'})
          obj.is_valid()
          Out[15]: True

渲染頁面

formmm.html

1.forms組件只會幫你渲染獲取用戶輸入(輸入,選擇,下拉框...)的標籤  提交按鈕須要你本身手動寫

<p>三種渲染前端頁面的方式</p>
<p>第一種渲染前端頁面的方式:封裝程度過高了 標籤樣式及參數不方便調整 可擴展性差(不推薦使用)
  {{ form_obj.as_p }}
  {{ form_obj.as_ul }}
  </p>

  <p>第二種渲染頁面的方式:擴展性較高 不足之處在於 須要你手寫的代碼量比較多(不推薦使用)</p>
    <p>
    {{ form_obj.username.label }}{{ form_obj.username }}
    </p>
    <p>
    {{ form_obj.password.label }}{{ form_obj.password }}
    </p>
    <p>
    {{ form_obj.email.label }}{{ form_obj.email }}
    </p>

    <p>第三種渲染前端頁面的方式:代碼量和擴展性都很高(推薦使用)</p>
      {% for foo in form_obj %}
      <p>{{ foo.label }}{{ foo }}</p>
      {% endfor %}

      如何展現錯誤信息
      如何取消前端幫咱們作的校驗 form表單中添加一個參數便可
      <form action="" method="post" novalidate>

      展現錯誤信息   用對象點errors.0
      <form action="" method="post" novalidate>
      {% for foo in form_obj %}
      <p>
      {{ foo.label }}:{{ foo }}
        <span style="color: red">{{ foo.errors.0 }}</span>
        </p>
        {% endfor %}
        <input type="submit">
        </form>

views:

from django import forms


class MyRegForm(forms.Form):
  username = forms.CharField(min_length=3,max_length=8,label='用戶名',
                             error_messages={
                               'min_length':'用戶名最短三位',
                               'max_length':'用戶名最長八位',
                               'required':'用戶名不能爲空'
                             },initial='我是初始值',required=False
                            )
  password = forms.CharField(min_length=3,max_length=8,label='密碼',error_messages={
    'min_length':'密碼最短三位',
    'max_length':'密碼最長八位',
    'required':'密碼不能爲空'
  })
  email = forms.EmailField(label='郵箱',error_messages={
    'required':'郵箱不能爲空',
    'invalid':'郵箱格式不正確'
  },required=False)

forms組件展現錯誤

forms組件鉤子函數
        針對字段 你還能夠作額外的校驗   須要經過鉤子函數
        
        局部鉤子
            # 當你須要對某一個字段數據進行額外的一些列校驗 你能夠考慮使用鉤子函數
            # 針對單個字段的  使用局部鉤子
            def clean_username(self):
                username = self.cleaned_data.get('username')
                if '書名' in username:
                    # 給username字段下面提示錯誤信息
                    self.add_error('username','用戶名不符合社會主義核心價值觀')
                return username
        全局鉤子
            # 針對多個字段的校驗 使用全局鉤子      eg:校驗兩次密碼是否一致
            def clean(self):
                password = self.cleaned_data.get('password')
                confirm_password = self.cleaned_data.get('confirm_password')
                if not password == confirm_password:
                    self.add_error('confirm_password','兩次密碼不一致')
                return self.cleaned_data
        
        
            
    如何改變input框的type屬性值
        widget= widgets.TextInput()
        widget=widgets.PasswordInput()
    如何讓forms組件渲染出來的input框有form-control類屬性
        widget= widgets.TextInput(attrs={'class':'form-control others'})  # 若是有多個類屬性 空格隔開
        widget=widgets.PasswordInput(attrs={'class':'form-control others'})
        
            
    每一個字段 還支持正則校驗
        from django import forms
        from django.forms import Form
        from django.core.validators import RegexValidator
         
        class MyForm(Form):
            user = forms.CharField(
                validators=[RegexValidator(r'^[0-9]+$', '請輸入數字'), RegexValidator(r'^159[0-9]+$', '數字必須以159開頭')],
            )
相關文章
相關標籤/搜索