06-Django表單

d:/python/demo3

目標(biāo)

  • form表單
  • get/post
  • Request對(duì)象
  • 利用HTML表單開(kāi)發(fā)注冊(cè)功能
  • Django表單改造注冊(cè)功能
  • 數(shù)據(jù)綁定與校驗(yàn)(了解)
  • 數(shù)據(jù)驗(yàn)證錯(cuò)誤信息(了解)
  • 實(shí)戰(zhàn)任務(wù)

表單

表單有如下特征:

  • 1、通過(guò)各種<input>、<select>等標(biāo)簽進(jìn)行數(shù)據(jù)與參數(shù)的對(duì)應(yīng),用來(lái)作為數(shù)據(jù)載體,傳遞數(shù)據(jù)。
  • 2、在<form>標(biāo)簽中的action屬性定義url請(qǐng)求的地址。
  • 3、在<form>標(biāo)簽中的method屬性定義Http method。

get/post

get/post及區(qū)別略

Request對(duì)象

每個(gè)view函數(shù)的第一個(gè)參數(shù)是一個(gè)HttpRequest對(duì)象。
request對(duì)象的屬性
request.scheme
代表請(qǐng)求的方案,http或者h(yuǎn)ttps
request.path
請(qǐng)求的路徑,比如請(qǐng)求127.0.0.1/org/list,那這個(gè)值就是/org/list
request.method
表示請(qǐng)求使用的http方法,GET或者POST請(qǐng)求
request.encoding
表示提交數(shù)據(jù)的編碼方式
request.GET
獲取GET請(qǐng)求
request.POST
獲取post的請(qǐng)求,比如前端提交的用戶密碼,可以通過(guò)request.POST.get()來(lái)獲取
另外:如果使用 POST 上傳文件的話,文件信息將包含在 FILES 屬性中
request.COOKIES
包含所有的cookie
request.META
一個(gè)標(biāo)準(zhǔn)的Python 字典,包含所有的HTTP 首部。具體的頭部信息取決于客戶端和服務(wù)器,下面是一些示例:

CONTENT_LENGTH —— 請(qǐng)求的正文的長(zhǎng)度(是一個(gè)字符串)。
CONTENT_TYPE —— 請(qǐng)求的正文的MIME 類型。
HTTP_ACCEPT —— 響應(yīng)可接收的Content-Type。
HTTP_ACCEPT_ENCODING —— 響應(yīng)可接收的編碼。
HTTP_ACCEPT_LANGUAGE —— 響應(yīng)可接收的語(yǔ)言。
HTTP_HOST —— 客服端發(fā)送的HTTP Host 頭部。
HTTP_REFERER —— Referring 頁(yè)面。
HTTP_USER_AGENT —— 客戶端的user-agent 字符串。
QUERY_STRING —— 單個(gè)字符串形式的查詢字符串(未解析過(guò)的形式)。
REMOTE_ADDR —— 客戶端的IP 地址。
REMOTE_HOST —— 客戶端的主機(jī)名。
REMOTE_USER —— 服務(wù)器認(rèn)證后的用戶。
REQUEST_METHOD —— 一個(gè)字符串,例如"GET" 或"POST"。
SERVER_NAME —— 服務(wù)器的主機(jī)名。
SERVER_PORT —— 服務(wù)器的端口(是一個(gè)字符串)

request.user
一個(gè) AUTH_USER_MODEL 類型的對(duì)象,表示當(dāng)前登錄的用戶。
如果用戶當(dāng)前沒(méi)有登錄,user 將設(shè)置為 django.contrib.auth.models.AnonymousUser 的一個(gè)實(shí)例。你可以通過(guò) is_authenticated() 區(qū)分它們
把request傳給前端的時(shí)候,前端可以通過(guò) {% if request.user.is_authenticated %}判斷用戶時(shí)候登錄
request.session
一個(gè)既可讀又可寫的類似于字典的對(duì)象,表示當(dāng)前的會(huì)話

利用form表單開(kāi)發(fā)注冊(cè)功能

接下來(lái)我們使用HTML表單,模擬一個(gè)用戶注冊(cè)功能,并演示如何使用HTML表單以及request對(duì)象:

  1. 用戶的信息包括:用戶名、密碼、昵稱、郵件地址、自我介紹。
  2. 訪問(wèn)/register注冊(cè)頁(yè)面,填寫用戶信息,點(diǎn)擊[注冊(cè)]按鈕使用post方式提交表單。
  3. 提交后,后端校驗(yàn)數(shù)據(jù)有效性,用戶名/密碼/昵稱為必填項(xiàng),郵件地址中必須包含'@'。如果不滿足有效性,則給出提示。
  4. 通過(guò)有效性驗(yàn)證后,頁(yè)面跳轉(zhuǎn)到新的歡迎頁(yè),并回顯用戶數(shù)據(jù)。
    1)d:/python/demo3下新建Django工程
    (略)

2)命令行輸入以下命令,新建一個(gè)formapp,此應(yīng)用用于測(cè)試form

 python manage.py startapp formapp

3)setting.xml里注冊(cè)formapp

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'formapp',
]

4)主urls加入以下語(yǔ)句

path('forms',include("formapp.urls")),

5)formapp下新建urls.py 交輸入以下內(nèi)容

from django.urls import path
from . import views
urlpatterns = [
    path('', views.goregister, name='goregister'),
    path('register', views.register),
]

6)views.py

def register(request):
    errors = []
    user = {}
    if request.method == 'POST':
        if not request.POST.get('nickname', ''):
            errors.append('請(qǐng)輸入昵稱.')
        if not request.POST.get('username', ''):
            errors.append('請(qǐng)輸入用戶名.')
        if not request.POST.get('password', ''):
            errors.append('請(qǐng)輸入密碼.')
        if request.POST.get('email') and '@' not in request.POST['email']:
            errors.append('請(qǐng)輸入有效的郵件地址.')
        if not errors:
            user = {
                'nickname': request.POST['nickname'],
                'username': request.POST['username'],
                'password': request.POST['password'],
                'email': request.POST.get('email', ''),
                'self_intro': request.POST.get('self_intro', ''),
            }
            save_user(user)
            # 使用post提交的表單,Django要求必須使用csrf標(biāo)簽,渲染模板時(shí),請(qǐng)使用render方法
            return render(request, 'success.html', user)
    return render(request, 'register.html', {
        'errors': errors,
        'nickname': request.POST.get('nickname', ''),
        'username': request.POST.get('username', ''),
        'password': request.POST.get('password', ''),
        'email': request.POST.get('email', ''),
        'self_intro': request.POST.get('self_intro', ''),
    })
def save_user(user):
    # 省略保存用戶實(shí)現(xiàn)過(guò)程
    pass

7)頁(yè)面
formapp/templates目錄下新建register.html success.html
register.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Neuedu Django ch03</title>
</head>
<body>
    {% if errors %}
        <ul>
            {% for error in errors %}
            <li>{{ error }}</li>
            {% endfor %}
        </ul>
    {% endif %}

    <!-- action屬性不填寫時(shí),等同于將表單提交到當(dāng)前頁(yè)面的請(qǐng)求地址 -->
    <form action="/forms/register" method="post">
        {# csrf標(biāo)簽是Django提供的防止偽裝提交請(qǐng)求的功能。POST方法提交的表格,必須有此標(biāo)簽。 #}
        {% csrf_token %}
        <p>昵稱: <input type="text" name="nickname" value="{{ nickname }}" ></p>
        <p>用戶名: <input type="text" name="username" value="{{ username }}" ></p>
        <p>密碼: <input type="text" name="password" value="{{ password }}" ></p>
        <p>郵件地址: <input type="text" name="email" value="{{ email }}" ></p>
        <p>自我介紹: <textarea name="self_intro" rows="10" cols="50">{{ self_intro }}</textarea></p>
        <input type="submit" value="注冊(cè)">
    </form>

</body>
</html>

success.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Neuedu Django ch03</title>
</head>
<body>
<h1>恭喜注冊(cè)成功!您的用戶信息如下:</h1>
<p>昵    稱: {{ nickname }}</p>
<p>用 戶 名: {{ username }}</p>
<p>郵件地址: {{ email }}</p>
<p>自我介紹: {{ self_intro }}</p>
</body>
</html>

8)運(yùn)行效果


image.png
image.png

Django表單改造注冊(cè)功能(中英文兩套)

d:/python/demo3
上述功能,如果頁(yè)面需要提交的字段比較多,后臺(tái)views會(huì)特別麻煩。用Django表單組件可以簡(jiǎn)化這部分工作

Django帶有一個(gè)form庫(kù),稱為django.forms,這個(gè)庫(kù)可以處理包括HTML表單顯示以及驗(yàn)證的很多內(nèi)容。接下來(lái)我們來(lái)深入了解一下form庫(kù),學(xué)習(xí)如何使用Django表單,最后試著使用它來(lái)重寫我們的用戶注冊(cè)功能。
1)我們?cè)趕ettings目錄創(chuàng)建一個(gè)python文件,form.py,繼承自django.forms.Form,在RegisterForm中定義一些屬性,與模型寫法類似

from django import forms


class RegisterForm(forms.Form):
    nickname = forms.CharField(max_length=20)
    username = forms.CharField()
    password = forms.CharField()
    email = forms.EmailField(required=False)
    self_intro = forms.CharField(required=False, widget=forms.Textarea)

class RegisterFormChinese(forms.Form):
    nickname = forms.CharField(max_length=20, label='昵稱')
    username = forms.CharField(label='用戶名')
    password = forms.CharField(label='密碼')
    email = forms.EmailField(required=False, label='郵件地址')
    self_intro = forms.CharField(required=False, widget=forms.Textarea, label='自我介紹')

2)改造views.py關(guān)鍵代碼

from demo3.form import RegisterForm, RegisterFormChinese
def register(request):
    # get請(qǐng)求訪問(wèn)頁(yè)面時(shí),返回空表單,post請(qǐng)求提交數(shù)據(jù)時(shí)進(jìn)行表單驗(yàn)證和頁(yè)面跳轉(zhuǎn)
    if request.method == 'POST':
        form = RegisterForm(request.POST)
        if form.is_valid():
            return render(request, 'success.html', {'form': form})
    else:
        form = RegisterForm()
    return render(request, 'register.html', {'form': form})


def register_chinese(request):
    if request.method == 'POST':
        form = RegisterFormChinese(request.POST)
        if form.is_valid():
            # 將用戶提交的表單回顯,并設(shè)置不可編輯
            # form.fields 返回一個(gè)OrderedDict
            # 我們遍歷這個(gè)存儲(chǔ)著表單字段的字典,并通過(guò)widget.attrs設(shè)定他們的html屬性
            for f in form.fields.values():
                f.widget.attrs['disabled'] = 'disabled'
            return render(request, 'success.html', {'form': form})
    else:
        form = RegisterFormChinese()
    return render(request, 'register_chinese.html', {'form': form})

3)改造register.html

<form action="/forms/register/" method="post">
    {% csrf_token %}
    <table>{{ form }}</table>
    <input type="submit" value="Submit" />
</form>

4)register_chinese.html

<form action="/forms/register_chinese/" method="post">
    {% csrf_token %}
    <table>{{ form }}</table>
    <input type="submit" value="提交" />
</form>

4)改造success.html

<body>
<h1>注冊(cè)成功</h1>
<table>{{ form }}</table>
</body>

5)formapp.urls.py

from django.urls import path
from . import views
urlpatterns = [
    path('', views.goregister, name='goregister'),
    path('register/', views.register),
    path('register_chinese/', views.register_chinese),
]

6)啟動(dòng)服務(wù)

python manage.py runserver

7)瀏覽器輸入地址測(cè)試

http://127.0.0.1:8000/forms/register/
http://127.0.0.1:8000/forms/register_chinese/

數(shù)據(jù)綁定與校驗(yàn)證(了解)

form.is_bound()屬性查看表單對(duì)象是否已經(jīng)綁定
form.is_valid()是否所有字段驗(yàn)證通過(guò),返回True/False

數(shù)據(jù)驗(yàn)證錯(cuò)誤信息(了解)

f.errors()提供了一個(gè)字段與錯(cuò)誤消息相映射的字典表。

代碼解釋

我們將頁(yè)面展示與頁(yè)面提交的地址都設(shè)置為formapp/register
在視圖中通過(guò)request對(duì)象的method方法判斷頁(yè)面請(qǐng)求的get/post方法,進(jìn)行不同的操作。
當(dāng)頁(yè)面提交get請(qǐng)求時(shí)(直接訪問(wèn)url地址),初始化一個(gè)空的表單對(duì)象,并返回給頁(yè)面。
當(dāng)頁(yè)面提交post請(qǐng)求時(shí)(通過(guò)頁(yè)面html提交表單時(shí)),驗(yàn)證表單并跳轉(zhuǎn)到成功頁(yè)面。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容