天天看點

Web架構開發-Django-form元件django 之知識點總結以及Form元件

django 之知識點總結以及Form元件

一、model常用操作

  1、13個API查詢:all,filter,get ,values,values_list,distinct,order_by ,reverse , exclude(排除),count,first,last,esits(判斷是否存在)

  需要掌握的all、values、values_list

  • all:列印的是一個QuerySet集合,一個清單裡面放的對象
  • values:是一個字典形式
  • values_list:是一個元組形式

all的性能是最低的

  2、only和defer

datalist = models.Userinfo.objects.all().only("name","email")  #拿到的還是一個QuerySet集合,僅僅取name和email
for item in datalist:
    print(item.id)
    print(item.name)
    print(item.pwd)   #隻要表裡有這個字段,一樣會取到值,額外的會再發一次請求

datalist = models.Userinfo.objects.all().defer("name","email") #阻止,不取name和email
for item in datalist:
    print(item.id)
    print(item.pwd)
           

  注意:用only的話就去取only裡面的字段,取其它的字段效率太低了,盡可能的少的連接配接資料庫

  3、路由系統

  反向生成URL:

    有兩種方式:{% url “a1” %}

          reverse(“a1”)

用reverse需要導入: from django.core.urlresolvers import reverse

/index/     func    name=a1
    {% url "a1"}
     reverse('a1')
                
/index/(\d+)/     func    name=a2
    {% url "a2" 11 %}
    reverse('a2',args=(11,))
                
/index/(?P<nid>\d+)/     func    name=a3
    {% url "a2" nid=11 %}
    reverse('a3',kwargs={'nid':11})
           

  

def index(request):
    if request.method == "POST":
        """
        兩個return是一樣的,用url反向解析就相當于下面的路徑在urls裡面
        協商别名name="index",但在模闆中還是要用{%url"index"%}
        """
       # return redirect(reverse(index))
        return redirect("index.html")   # 跳轉到個人首頁
    return render(request, "hh.html")
           

  4、Django的生命周期

  web伺服器網關接口(Python Web Server Gateway Interface,縮寫為WSGI)

  1.   首先走wsgi子產品,這個子產品也是一個協定,包括wsgiref和uwsgi
  2. 然後路由配置設定---------views視圖
  3. 從資料庫取資料--------渲染到HTML

 

二、form元件

一、Form元件介紹

Form元件可以做的幾件事情:

  1、使用者請求資料驗證

  2、自動生成錯誤資訊    

  3、打包使用者送出的正确資訊

  4、如果其中有一個錯誤了,其他的正确這,保留上次輸入的内容

  4、自動建立input标簽并可以設定樣式

二、Form元件的使用

  1、建立規則

class Foo(Form)    # 必須繼承
        username = XXX
        password = XXX
        email = XXX
注意這裡的字段必須和input字段一緻
           

  2、資料和規則進行比對

先導入view.py

from django.forms import Form
from django.forms import fields
from django.forms import widgets
           

  

# 1、建立規則
class TeacherForm(Form):    # 必須繼承form
    # 建立字段,本質上是正規表達式
    username = fields.CharField(
        required=True,   # 必填字段
        error_messages={"required": "使用者名不能為空!"},
        widget=widgets.TextInput(attrs={"placeholder": "使用者名","class": "form-control"})   # 自動生成input框
    )
    password = fields.CharField(
        required=True,
        error_messages={'required': '密碼不能為空!'},
        widget=widgets.TextInput(attrs={'placeholder': '密碼', 'class': 'form-control'})
    )
    email = fields.EmailField(
        required=True,
        error_messages={"requeired": "郵箱不能為空!",
                        "invalid": "無效的郵箱格式"},
        widget=widgets.EmailInput(attrs={"placeholder":"郵箱", "class": "form-control"})
    )


# 2、使用規則:将資料和規則進行比對
def teacherindex(request):
    teacher_obj = models.UserInfo.objects.all()
    print(teacher_obj)

    return render(request, "teacherindex.html", {"teacher_obj": teacher_obj})


def add(request):
    if request.method == "GET":
        form = TeacherForm()    # 隻是顯示一個input框
        return render(request, "add.html", {"form": form})
    else:
        form = TeacherForm(data=request.POST)

        if form.is_valid(): # 開始驗證
            form.cleaned_data['ut_id'] = 1  # 要分的清是班主任還是講師
            models.UserInfo.objects.all().create(**form.cleaned_data)
            return redirect("/teacherindex/")

        else:
            return render(request, "add.html", {"form": form})
           

  add.html

<!DOCTYPE html>
<html >
<head>
    <meta charset="UTF-8">
    <title>添加老師資訊</title>
</head>
<body>
<form method="post" novalidate>
    {% csrf_token %}
    <p>姓名:{{ form.username }}</p>{{ form.errors.username.0 }}
    <p>密碼:{{ form.password }}</p>{{ form.errors.password.0 }}
    <p>郵箱:{{ form.email }}</p>{{ form.errors.email.0 }}
    <p><input type="submit" value="送出"></p>
</form>

</body>
</html>
           

  

teacherindex.html
           
<!DOCTYPE html>
<html >
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-8">
            <table class="table-bordered table-striped">
                <thead>
                    <tr>
                        <th>編号</th>
                        <th>姓名</th>
                        <th>郵箱</th>
                    </tr>
                </thead>
                <tbody>
                    {% for teacher in teacher_obj %}
                    <tr>
                        <td>{{ teacher.id }}</td>
                        <td>{{ teacher.username }}</td>
                        <td>{{ teacher.email }}</td>
                    </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</div>

</body>
</html>
           

  

  如果通路視圖的是一個

GET

 請求,它将建立一個空的表單執行個體并将它放置到要渲染的模闆的上下文中。這是我們在第一個通路該URL 時預期發生的情況。

  如果表單的送出使用

POST

 請求,那麼視圖将再次建立一個表單執行個體并使用請求中的資料填充它:

form = NameForm(request.POST)

。這叫做”綁定資料至表單“(它現在是一個綁定的表單)。

  我們調用表單的

is_valid()

方法;如果它不為

True

,我們将帶着這個表單傳回到模闆。這時表單不再為空(未綁定),是以HTML 表單将用之前送出的資料填充,然後可以根據要求編輯并改正它。

  如果

is_valid()

True

,我們将能夠在

cleaned_data

 屬性中找到所有合法的表單資料。在發送HTTP 重定向給浏覽器告訴它下一步的去向之前,我們可以用這個資料來更新資料庫或者做其它處理。

  備注: form = TeacherForm()  #沒有參數,隻是一個input框

    form = TeacherForm(data=request.POST) # 資料和規則放置一起 (添加的時候用)

    form = TeacherForm(initial={'username':obj.username,'password':obj.password,'email':obj.email})   # 顯示input,并且将資料庫中的預設值填寫到input框中 (編輯的時候用)

Widgets

每個表單字段都有一個對應的

Widget

 類,它對應一個HTML 表單

Widget

,例如

<input type="text">

在大部分情況下,字段都具有一個合理的預設Widget。例如,預設情況下,

CharField

 具有一個

TextInput Widget

,它在HTML 中生成一個

<input type="text">

字段的資料

不管表單送出的是什麼資料,一旦通過調用

is_valid()

 成功驗證(

is_valid()

 傳回

True

),驗證後的表單資料将位于

form.cleaned_data

 字典中。這些資料已經為你轉換好為Python 的類型。

注:此時,你依然可以從

request.POST

 中直接通路到未驗證的資料,但是通路驗證後的資料更好一些。

在上面的聯系表單示例中,is_married将是一個布爾值。類似地,

IntegerField

 和

FloatField

 字段分别将值轉換為Python 的

int

 和

float

三、資料庫表設計

設計表時注意的幾點:

  1、 nid = models.AutoField(primary_key=True)        #如果不指定django會預設加上id的

    nid = models.BigAutoField(primary_key=True)   #但那些整型滿足不了你的時候,就用BigAutoField

  2、對于類的注釋一般加在類裡面

  3、verbose_name=“标題”   字段的中文提示

  4、ForeignKey(to = "表名",tofield= "字段")    #這兩個to可以不用寫,但是關聯的表名一定要寫

  5、releated_name = "uuu"   反向查詢。如果一個表中有多個ManyTwoMany()或者ForeignKey()必須加上releated_name 

  6、字段經常變動的适合連表

     字段變化小,不怎麼變的适合在一個表中,不進行連表:就用choices

       吧班主任和老師可以放到一個表中、因為他們有相同的屬性,如果屬性全是一樣的,可以放在一個表裡(推薦)

     也可以分開放,老師表是老師表,班主任表是班主任表。這樣就會進行連表操作,連表有性能消耗。

舉例:文章和文章類型

   分析:一個文章有一個類型,一個類型可以對應多個文章(是以文章和文章類型是一對多的關系,關聯字段要放在多的一方)

  一:連表設計:

class News(models.Model):
    title = models.CharField(max_length=32)
    summary = models.CharField(max_length=255)
    news_type = models.ForeignKey(to="NewsType")
class NewsType(models.Model):
    type_title = models.CharField(max_length=32)


News:
  id   title   summary  news_type_id
   t....    科技...     2
   t....    科技...     1
   t....    科技...     2
NewsType:
 id    title
     圖檔
     挨踢1024
     段子
 
# 檢視所有新聞
				new_list = models.News.objects.all()
				for row in new_list:
					print(row.title,row.summary,row.news_type.title)
           

  二 :放在一個表中的操作:choices

class News2(models.Model):
    title = models.CharField(max_length=32)
    summary = models.CharField(max_length=255)
    news_type_chices = (
        (1, '圖檔'),
        (4, '挨踢1024'),
        (3, '段子'),
    )
    news_type = models.IntegerField(choices=news_type_chices)


# 檢視所有新聞
				new_list = News.objects.all()
				for row in new_list:
					print(row.title,row.summary,  row.get_news_type_display()  )
           

  

舉例二:使用者和使用者類型

  一:連表設計

class UserType(models.Model):
        """
        使用者類型表,個數經常變動
        """
        title = models.CharField(max_length=32)

class UserInfo(models.Model):
        """
        使用者表:講師和班主任
        """
        username = models.CharField(max_length=32)
        password = models.CharField(max_length=64)
        email = models.CharField(max_length=32)
        ut = models.ForeignKey(to="UserType")
           

  二:不連表設計:choices

class UserInfo(models.Model):
#     """
#     使用者表
#     """
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
    email = models.CharField(max_length=32,verbose_name="郵箱")
    user_type_choices = (
        (1, '班主任'),
        (2, '講師'),
    )

    user_type_id = models.IntegerField(choices=user_type_choices)
           

  

四、登入

 可設定一個裝飾器

def auth(func):
    def inner(request,*args,**kwargs):
        is_login = request.session.get("is_login", None)
        if not is_login:
            return redirect("/login/")
        ret = func(*args,**kwargs)
        return ret
    return inner
           

  

 需要注意的:  

  1、action不寫路徑,預設送出到目前 

  2、向背景送出資料用post,擷取資料用get

  3、submit一般加上value,有些浏覽器可能會不識别

  4、一般配置檔案的鍵都是大寫的

 五、Form基本使用

類
字段
is_valid()
cleaned_data
errors

字段參數:
    max_length
    min_length
    validators = [RegexValidators("XXX")]

鈎子函數:
    clean_字段名
    注意:
        必須有傳回值
        隻能拿自己目前字段值
        raise ValidationError("XXX")
    
 下拉框資料源時時更新:
        1、重寫init方法
            先執行父類構造方法
            self.fields["xx"].choices = XXXX
        2、ModelChoiceField
           

  使用者登入

- form的字段可以定義正規表達式
            password = fields.CharField(
                required=True,
                min_length=3,
                max_length=18,
                error_messages={
                    'required': '密碼不能為空',
                    'min_length': '密碼長度不能小于3',
                    'max_length': '密碼長度不能大于18',
                    'invalid': '密碼格式錯誤',
                },
                validators=[RegexValidator('\d+','隻能是數字') ]
            )
            注意:error_messages的優先級比validators高
           

 

class LoginForm(Form):
    username = fields.CharField(
        required=True,  #必填字段
        min_length=3,
        max_length=16,
        error_messages={
            "required":"使用者名不能為空",
            "min_length":"長度不能小于3",
            "max_length":"長度不能大于16"
        },
        widget=widgets.TextInput({"placeholder":"username","class":"form-control"})
    )
    password = fields.CharField(
        required=True,
        min_length=3,
        max_length=16,
        error_messages={
            "required": "密碼不能為空",
            "min_length": "密碼長度不能小于3",
            "max_length": "密碼長度不能大于16",
            # "invalid":"密碼格式錯誤"
            # error_messages的優先級高,如果寫上"invalid":"密碼格式錯誤"這個就會優先顯示這個錯誤
        },
        widget=widgets.PasswordInput({"placeholder":"password","class":"form-control"}),
        validators=[RegexValidator("\d+","密碼隻能是數字")]  #可以進行正則比對提示錯誤
    )

    def clean_username(self):
        user = self.cleaned_data["username"]
        is_exits = models.UserInfo.objects.filter(username=user).count()
        if not is_exits:
            raise ValidationError("使用者名和密碼錯誤")
        return user   #必須有return
           

  

- 主動向form中添加錯誤資訊

  # form.add_error('password','使用者名或密碼錯誤')

  form.add_error('password',ValidationError('使用者名或密碼錯誤'))

  這兩個都可以,建議用第二個 

 

Form擴充(鈎子函數)

如果對username做擴充

#先做正規表達式判斷

#然後自定義方法驗證:也就是clean_xx,稱為鈎子函數

def clean_username(self):
        #可以寫自己的驗證提示
        不像validators隻寫正規表達式。在這裡可以随意寫
        user=self.clean_data["username"]
        is_esits = models.UserInfo.objects.filter(username=user).count()
        if not is_esits:
            raise validationError("使用者名不存在")
        return user   #必須有傳回值
    如果 def clean_username(self):  隻能取password字段的值
    如果 def clean_username(self):  隻能取username字段的值
    注意:在自己寫鈎子函數的時候,隻能拿自己的字段不能拿别人的
    每一種字段就可以用 正則+自定義正則+自定義鈎子函數
           

  

轉載于:https://www.cnblogs.com/mike-liu/p/9784515.html