python初試四

chatGPT發表於2023-12-25

我們在上一課中講到了伺服器上的資料。當時我們是用手動的方式,直接在資料庫插入資料。我們將允許客戶向伺服器傳遞資料。


表格是客戶向伺服器傳資料的經典方式。我們先會看到傳統的表格提交,然後瞭解Django的表格物件。


html表格


HTTP協議以“請求-回覆”的方式工作。客戶傳送請求時,可以在請求中附加資料。伺服器透過解析請求,就可以獲得客戶傳來的資料,並根據URL來提供特定的服務。 


(http協議的運作方式,詳見http協議)


 


HTML檔案中可以包含表格標籤。HTML表格的目的是幫助使用者構成HTTP請求,把資料用GET或者POST的方法,傳遞給某一URL地址。下面是一個表格的例子:

<form action="/west/investigate/" method="get">

  <input type="text" name="staff">

  <input type="submit" value="Submit">

</form>


這裡的form標籤有兩個屬性。action用於說明URL地址,method說明請求的方法。


表格中還包含有兩個input標籤,即兩個輸入欄目。根據type的不同,第一個為一個文字框,第二個為一個提交按鈕。name為輸入欄的名字。伺服器在解析資料時,將以name為索引。


 


我們可以將上面的表格直接存入模板form.html,並在west/views.py中定義一個檢視form()來顯示錶格:


from django.shortcuts import render


def form(request):

    return render(request, 'form.html')


設定urls.py,讓對[site]/west/form/的訪問,指向該檢視。


 


最後,我們在west/views.py中定義investigate()來處理該表格提交的資料:


from django.shortcuts import render


def investigate(request):

    rlt = request.GET['staff']

    return HttpResponse(rlt)


可以看到,HTTP請求的相關資訊,包括請求的方法,提交的資料,都包含在request引數中。


表格是透過GET方法提交的。我們可以透過request.GET['staff'],來獲得name為staff的輸入欄的資料。該資料是一個字串。investigate()將直接顯示該字串。


設定urls.py,讓該處理函式對應action的URL([site]/west/investigate/)。


 


當我們訪問時,將顯示:


提交表格後,頁面將轉到[site]/west/investigate。investigate()讀取字串後,在頁面上顯示出來。


POST方法

上面我們使用了GET方法。檢視顯示和請求處理分成兩個函式處理。


提交資料時更常用POST方法。我們下面使用該方法,並用一個URL和處理函式,同時顯示檢視和處理請求。


 


先建立模板investigate.html


<form action="/west/investigate/" method="post">

  {% csrf_token %}

  <input type="text" name="staff">

  <input type="submit" value="Submit">

</form>


<p>{{ rlt }}</p>


我們修改提交表格的方法為post。在模板的末尾,我們增加一個rlt記號,為表格處理結果預留位置。


表格後面還有一個{% csrf_token %}的標籤。csrf全稱是Cross Site Request Forgery。這是Django提供的防止偽裝提交請求的功能。POST方法提交的表格,必須有此標籤。


 


在west/views.py中,用investigate()來處理表格:


from django.shortcuts import render

from django.core.context_processors import csrf


def investigate(request):

    ctx ={}

    ctx.update(csrf(request))

    if request.POST:

        ctx['rlt'] = request.POST['staff']

    return render(request, "investigate.html", ctx)


這裡的csrf()是和上面的{% csrf_token %}對應。我們在這裡不深究。


看程式的其它部分。對於該URL,可能有GET或者POST方法。if的語句有POST方法時,額外的處理,即提取表格中的資料到環境變數。


 


最終效果如下:


儲存資料

我們還可以讓客戶提交的資料存入資料庫。使用莊園疑雲中建立的模型。我們將客戶提交的字串存入模型Character。


 


修改west/views.py的investigate():


from django.shortcuts import render

from django.core.context_processors import csrf


from west.models import Character


def investigate(request):

    if request.POST:

        submitted  = request.POST['staff']

        new_record = Character(name = submitted)

        new_record.save()

    ctx ={}

    ctx.update(csrf(request))

    all_records = Character.objects.all()

    ctx['staff'] = all_records

    return render(request, "investigate.html", ctx)


在POST的處理部分,我們呼叫Character類建立新的物件,並讓該物件的屬性name等於使用者提交的字串。透過save()方法,我們讓該記錄入庫。


隨後,我們從資料庫中讀出所有的物件,並傳遞給模板。


 


我們還需要修改模板investigate.html,以更好的顯示:


<form action="/west/investigate/" method="post">

  {% csrf_token %}

  <input type="text" name="staff">

  <input type="submit" value="Submit">

</form>


{% for person in staff %}

<p>{{ person }}</p>

{% endfor %}


我們使用模板語言的for,來顯示所有的記錄。


 


效果如下:


表格物件

客戶提交資料後,伺服器往往需要對資料做一些處理。比如檢驗資料,看是否符合預期的長度和資料型別。在必要的時候,還需要對資料進行轉換,比如從字串轉換成整數。這些過程通常都相當的繁瑣。


Django提供的資料物件可以大大簡化這一過程。該物件用於說明表格所預期的資料型別和其它的一些要求。這樣Django在獲得資料後,可以自動根據該表格物件的要求,對資料進行處理。


 


修改west/views.py:


from django.shortcuts import render

from django.core.context_processors import csrf


from west.models import Character


from django import forms


class CharacterForm(forms.Form):

    name = forms.CharField(max_length = 200)


def investigate(request):

    if request.POST:

        form = CharacterForm(request.POST)

        if form.is_valid():

            submitted  = form.cleaned_data['name']

            new_record = Character(name = submitted)

            new_record.save()


    form = CharacterForm()

    ctx ={}

    ctx.update(csrf(request))

    all_records = Character.objects.all()

    ctx['staff'] = all_records

    ctx['form']  = form

    return render(request, "investigate.html", ctx)


上面定義了CharacterForm類,並透過屬性name,說明瞭輸入欄name的型別為字串,最大長度為200。


在investigate()函式中,我們根據POST,直接創立form物件。該物件可以直接判斷輸入是否有效,並對輸入進行預處理。空白輸入被視為無效。


後面,我們再次建立一個空的form物件,並將它交給模板顯示。


 


在模板investigate.html中,我們可以直接顯示form物件:


<form action="/west/investigate/" method="post">

  {% csrf_token %}

  {{ form.as_p }}

  <input type="submit" value="Submit">

</form>


{% for person in staff %}

<p>{{ person }}</p>

{% endfor %}


如果有多個輸入欄,我們可以用相同的方式直接顯示整個form,而不是加入許多個<input>標籤。


 


效果如下:


來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70026630/viewspace-3001491/,如需轉載,請註明出處,否則將追究法律責任。

相關文章