目録
フォーム (Webページ内の検索)
2023-01-21
フォームとは
フォームとはWebページに訪問した人が入力するための欄のこと。ここでは訪問者にキーワードを入力してもらい、今まで登録したWebページの中からキーワードに一致する内容のページを一覧にして表示する。そして表示されたページを選ぶとそのページに移動できるようにする。
一つ一つのページをhtmlで列挙していくのは骨が折れる。しかし、すでにモデルを使ってページを登録しているため少しの手間で表示することができる。
フォームの作成
まずフォームを作るためのURLを設置する。urls.py
に以下を記入する。
コード1.
/ProjectName/webpage/urls.py
from django.urls import path
from . import views
app_name = 'webpage'
urlpatterns = [
path('' , views.index, name ='index' ),
path( 'category/', views.category , name = 'category') ,
path( 'category/<slug:title>/', views.title , name = 'title') ,
]
次にフォームクラスを実装する。ProjectNmae/webpage/にforms.py
というファイルを作り以下のようにWebpageForm
クラスを導入する。フォームにはキーワードの入力フィールドとしてform_keyword
とform_keyword2
の2つを用意した。
コード2.
/ProjectName/webpage/forms.py
from django import forms
class WebpageForm(forms.Form):
form_keyword = forms.CharField(label =' キーワード ' , max_length =150 , required =False )
form_keyword2 = forms.CharField(label =' キーワード 2' , max_length =150 , required =False )
required
によってフォームの入力が必須かどうかを決められる。
urls.py
でviews.py
のcategory
関数で表示の制御を行うようにした。views.py
を以下のようにする。
コード3.
/ProjectName/webpage/views.py
from django.core.paginator import Paginator
from django.shortcuts import render
from .models import Webpage
from .forms import WebpageForm
def index (request):
return render(request, 'index.html' )
def category (request):
form_set = WebpageForm()
model = Webpage.objects.all()
context = {
'form_set' : form_set,
'models' : model
}
return render(request, 'category.html' , context)
def title (request, **kwargs):
model = Webpage.objects.filter(webpage_url =kwargs['title' ]).first()
if model is not None:
context = {
'title' : model.webpage_title,
'contents' : model.webpage_contents,
}
return render(request, 'title.html' , context)
model = Webpage.objects.all()
で登録したすべてのページを呼び出している。
そしてcategory.html
で実際に表示内容を記述する。
コード4.
/ProjectName/webpage/templates/category.html
<!DOCTYPE html >
<html lang ="ja" >
<head>
<meta charset ="UTF-8" >
<title>Web ページ 検索 </title>
</head>
<body>
<div style=" text-align: center ; " >
<h1>Web ページの検索 </h1>
</div>
<form action="" method="post" >
{% csrf_token %}
<div>
{% for field in form_set %}
{{ field .errors }}
<p> {{ field .label_tag }} {{ field }}</p>
{% endfor %}
</div>
<button type ="submit" >検索 </button>
</form>
<hr>
<p> Webページ一覧 </p>
<hr>
<hr>
{% for model in models %}
<div>
<h4><a href=" {% url "webpage:title" model. webpage_url %} " > {{ model. webpage_title }} </a></h4>
<p> {{ model. webpage_contents }} </p>
</div>
<hr>
{% endfor %}
</body>
</html>
context
によってform_set
とmodels
がhtml内で使えるようになっている。form_set
からは2つの入力欄をfor文によって順に取り出して表示している。models
も同様にfor文を回し登録したページを取り出している。{% ... %}
はdjangoの特殊なhtml記法。
ターミナルでpython manage.py runserver
として「http://127.0.0.1:8000/webpage/category/ 」にアクセスすると、フォームとページ一覧が表示される。
ページネーション
登録したページが多くなると下に長くページが続き、とても見づらくなる。そこでページネーションと言われるものを使うとページを複数に区切ることができる。views.py
のcategory
関数を以下のようにする。
コード5.
/ProjectName/webpage/views.py
def category (request):
form_set = WebpageForm()
model = Webpage.objects.all()
paginator = Paginator(model, per_page =3 )
page_number = request.GET.get('page' )
model = paginator.get_page(page_number)
context = {
'form_set' : form_set,
'models' : model
}
return render(request, 'category.html' , context)
Paginator
を使ってper_page = 3
としているように登録したWebページを3つずつ表示するように設定している。登録数が15なら15/3=5ページに区切られる。per_page = 5
とすれば15/5=3ページに区切られる。区切られたページにアクセスできるようにするためcategory.html
を以下のようにする。現在、前後、最初と最後のページを表示するようにしている。
コード6.
/ProjectName/webpage/templates/category.html
<!DOCTYPE html >
<html lang ="ja" >
<head>
<meta charset ="UTF-8" >
<title>Web ページ 検索 </title>
</head>
<body>
<div style=" text-align: center ; " >
<h1>Web ページの検索 </h1>
</div>
<form action="" method="post" >
{% csrf_token %}
<div>
{% for field in form_set %}
{{ field .errors }}
<p> {{ field .label_tag }} {{ field }}</p>
{% endfor %}
</div>
<button type ="submit" >検索 </button>
</form>
<hr>
<p> Webページ一覧 </p>
<hr>
<hr>
{% for model in models %}
<div>
<h4><a href=" {% url "webpage:title" model. webpage_url %} " > {{ model. webpage_title }} </a></h4>
<p> {{ model. webpage_contents }} </p>
</div>
<hr>
{% endfor %}
{% if models. has_next %}
{% if models .number != 1 %}
<a href="?page= {{ models. previous_page_number }} " > 前のページ ({{ models. previous_page_number }}) </a>
{% endif %}
<a href="?page= {{ models. number }} " > 現在のページ ({{ models. number }}) </a>
<a href="?page= {{ models. next_page_number }} " > 次のページ ({{ models. next_page_number }}) </a>
<a href="?page= {{ models. paginator. num_pages }} " > 最後のページ » ({{ models. paginator. num_pages }}) </a>
{% elif models. has_previous %}
<a href ="?page=1"> 最初 « (1) </a>
<a href="?page= {{ models. previous_page_number }} " > 前のページ ({{ models. previous_page_number }}) </a>
<a href="?page= {{ models. number }} " > 現在のページ ({{ models. number }}) </a>
{% endif %}
</body>
</html>
フォームの送信 (GETとPOST)
今のところフォームに記入して送信を押しても何も変化はないが、実は内部的には送信によって状態が変化している。そのため訪問者に記入してもらったフォームは一度送信され、送信されたフォームに基づいてページを書き換える仕組みがあれば良い。
フォームが送信されていない状態は「GET」フォームが送信された状態は「POST」と呼ばれている。djangoにもGETかPOSTを判断する方法がある。POSTのときに入力欄にキーワードがあるはずなのでそれに基づいて一覧内容を書き換えるようにする。views.py
のcategory
関数を以下のようにする。
コード7.
/ProjectName/webpage/views.py
def category (request):
form_set = WebpageForm()
model = Webpage.objects.all()
paginator = Paginator(model, per_page =3 )
page_number = request.GET.get('page' )
model = paginator.get_page(page_number)
if request.method == 'POST' :
form_set = WebpageForm(request.POST)
if request.POST['form_keyword' ] != '' :
model = model.filter(webpage_contents__contains =request.POST['form_keyword' ])
if request.POST['form_keyword2' ] != '' :
model = model.filter(webpage_contents__contains =request.POST['form_keyword2' ])
context = {
'form_set' : form_set,
'models' : model
}
return render(request, 'category.html' , context)
request.method
によってGETかPOSTを判断し、POSTならrequest.POST
にWebpageForm
クラスの変数名をキーワードとしてフォームに記入された値がわかる。そのキーワードが空白でなければWebページの内容の中で一致するものを抽出している。