[Python+Django]初心者筆記11(form表單介紹 part1)
預計新增一個圖書館員才有權限的功能,讓他可以幫讀者更新書本到期的日期
先新增這個檔案locallibrary/catalog/forms.py,內容是:
forms.py是專門用來驗證表單是否正確用的
from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
import datetime #for checking renewal date range.
class RenewBookForm(forms.Form):
#取得表單的input資料
renewal_date = forms.DateField(help_text="Enter a date between now and 4 weeks (default 3).")
#clean_OOXX就是用來驗證這個欄位的
def clean_renewal_date(self):
data = self.cleaned_data['renewal_date']
#Check date is not in past.
if data < datetime.date.today():
raise ValidationError(_('Invalid date - renewal in past'))
#Check date is in range librarian allowed to change (+4 weeks).
if data > datetime.date.today() + datetime.timedelta(weeks=4):
raise ValidationError(_('Invalid date - renewal more than 4 weeks ahead'))
# Remember to always return the cleaned data.
return data
然後在locallibrary/catalog/urls.py最下面加入:
#圖書館管理人員限定的 更新讀者書本到期日的功能
#網址格式:/catalog/book/<bookinstance id>/renew/
#renew_book_librarian是底線分隔,表示這是一個function-based view
urlpatterns += [
path('book/<uuid:pk>/renew/', views.renew_book_librarian, name='renew-book-librarian'),
]
再來於locallibrary/catalog/views.py加入:
#renew_book_librarian用於讀書館員幫讀者手動更新書的到期日
from django.contrib.auth.decorators import permission_required
from django.shortcuts import get_object_or_404
from django.http import HttpResponseRedirect
from django.urls import reverse
import datetime
from .forms import RenewBookForm
#加上適當的權限,限制此功能只有圖書館員可使用
@permission_required('catalog.can_edit_all_borrowed_books')
def renew_book_librarian(request, pk):
"""
View function for renewing a specific BookInstance by librarian
"""
#執行query到db找這筆資料
#找不到這筆資料的話,會丟出404網頁錯誤
book_inst=get_object_or_404(BookInstance, pk = pk)
#if post == true, 表示是user編輯完畢
# If this is a POST request then process the Form data
if request.method == 'POST':
# 透過forms.py去驗證使用者提交的欄位value是否合法
# Create a form instance and populate it with data from the request (binding):
form = RenewBookForm(request.POST)
#透過reverse,可以將url.py的name轉成實際的網址
# Check if the form is valid:
if form.is_valid():
# process the data in form.cleaned_data as required (here we just write it to the model due_back field)
book_inst.due_back = form.cleaned_data['renewal_date']
book_inst.save()
# redirect to a new URL:
return HttpResponseRedirect(reverse('all-borrowed') )
#if post == false, 表示是user初次載入這個編輯頁,僅給予一些欄位預設value而已
#預設給讀者多三個禮拜的時間續借
# If this is a GET (or any other method) create the default form.
else:
proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3)
form = RenewBookForm(initial={'renewal_date': proposed_renewal_date,})
return render(request, 'catalog/book_renew_librarian.html', {'form': form, 'bookinst':book_inst})
接著請新增template檔/catalog/templates/catalog/book_renew_librarian.html,內容如下:
{% extends "base_generic.html" %}
{% block content %}
<!-- book_inst的由來是views.py -->
<h1>Renew: {{bookinst.book.title}}</h1>
<p>Borrower: {{bookinst.borrower}}</p>
<p{% if bookinst.is_overdue %} class="text-danger"{% endif %}>Due date: {{bookinst.due_back}}</p>
<form action="" method="post">
{% csrf_token %}
<table>
<!-- forms.py定義的欄位將會自動在下面的form變數裡面產生 -->
{{ form }}
</table>
<input type="submit" value="Submit" />
</form>
<!-- 讓畫面上的date欄位有可愛的UI可以快速選取日期 -->
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$( function() {
$( "#id_renewal_date" ).datepicker( { dateFormat: 'yy-mm-dd' } );
} );
</script>
{% endblock %}
為了方便測試上面新增的部分,我們在上一篇文章
[Python+Django]初心者筆記11(authentication,authorization,login驗證機制範例,permission權限機制範例)
的bookinstance_list_borrowed_all.html所列出的每本書籍的後面加入以下這段,這樣就方便使用本篇新增的功能,去更新每個借出去的書本的到期時間:
- <a href="{% url 'renew-book-librarian' bookinst.id %}">Renew</a>
測試只要以圖書館員身份登入之後打開網頁http://127.0.0.1:8000/catalog/borrowed/,即可透過"ReNew"按鈕更新書本的到期日了:
這篇先這樣,其他的在part2才繼續,不然篇幅太長……
參考資料:
Django Tutorial Part 9: Working with forms
https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Forms