djangoの実装を進める中で、お問い合わせフォームを作りたいという場合がありますよね。
ただ、実装するのは少し大変ですよね。
そこで今回は、お問い合わせフォームの作り方を分かりやすくかみ砕いて解説していきます。
お問い合わせフォームを構成する2つの要素
まずは、お問い合わせフォームを作るために必要な2つの要素を確認しましょう。
1. フォーム
まずは、問い合わせの内容を受け付けるためのフォームが必要です。
2. メール送信
また、受け取ったデータを送信するためにメールを送る機能が必要です。
メールを送る方法については、メールを送る方法を解説という記事を参考にしてください。
フォームの実装
早速フォームの実装を進めていきましょう。今回は、class based viewの場合とfunction based viewの場合の2つに分けて実装を進めていきます。
初めに書く基本的なコードは初期設定コードという記事にまとめていますので、そちらの記事を参考にしてください。
初期設定コードに追加で書いていく共通コードをここから書いていきます。
コード-BASE/djangoproject/forms.py
from django import forms
class ContactForm(forms.Form)
title = forms.CharField(max_length=50)
email = forms.EmailField()
content = forms.CharFiedl(max_length=500)
コード-BASE/app/urls.py
from django.urls import path, include
from .views import ContactView, contact, success
urlpatterns = [
path('contact/', ContactView.as_view(), name='contact'),
path('fbv/', contact, name='contactfbv'),
path('thanks/', success, name='success'),
[
コード-BASE/templates/form.html
<h1>Contact Us</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<div class="form-actions">
<button type="submit">Send</button>
</div>
</form>
これで初期設定は完了です。早速お問い合わせフォームの実装を進めていきましょう。
class based viewでの実装
まずはclass based viewでの実装を進めていきましょう。
コード-BASE/app/forms.py
1 class InquiryForm(forms.Form):
2 title = forms.CharField(max_length=100)
3 content = forms.textField()
4 email = forms.EmailField()
5 def send_email(self):
6 send_email()
7 pass
コード-BASE/app/views.py
from .forms import InquiryForm
from django.views.generic import FormView
8 class InquiryView(FormView):
9 template_name = 'contact.html'
10 form_class = Inquiryform
11 success_url = '/'
12 def form_valid(self, form):
13 form.send_mail()
14 return super().form_valid(form)
ちょっとややこしいコードですよね。
どういった流れでコードが実行されていくのかを順にみていきましょう。
コードの解説(1) まずは12行目をみてみましょう。InquiryViewの中でform_validメソッドを定義しました。
このform_validメソッドは、リクエストが「post」で送られたときに実行されるというのがポイントです。
つまり、はじめにurlpatternに合致してInquiryViewが呼び出されるときは、getリクエストですのでform_validメソッドは呼ばれません。
そして、template_nameで定義したhtmlファイルで書いたフォームにもとづき、送信ボタンを押すとpostでリクエストが送られます。
その結果、同じページがpostメソッドでリクエストされますので、form_validメソッドが実行されるという仕組みです。
(2) 13行目をみてみましょう。form_validメソッドの中でform.send_emailメソッドを呼び出しています。
ここでのformはContactFormから作られたオブジェクトですので、ContactFormで定義したsend_emailメソッドを呼び出しています。
(3) 6行目のsend_mailメソッドが呼び出されます。結果、メールが送信されます。
簡単にまとめると、postでリクエストが送られることによってform_validメソッドが呼ばれ、form_validメソッドの中でメールを送信するメソッドを呼び出すように設定することで、メールが送れるようにしているのです。
function based viewでの実装
次に、function based viewでの実装方法を見ていきましょう。
コード-BASE/app/forms.py
class InquiryForm(forms.Form):
title = forms.CharField(max_length=100)
content = forms.textField()
email = forms.EmailField()
class based viewで書いたInquryFormと比べると、send_emailメソッドがなくなっていることが分かります。つまり、forms.pyファイルの中でメールを送る処理は行いません。
メール送信処理をどこで行うのかというと、views.pyファイルの中です。
つまり、function based viewでは、views.pyファイルの中でリクエストを受けてからメールを送信するまでの一連の処理が書かれます。
では、コードを見ていきましょう。
コードfrom django.core.mail import send_mail, BadHeaderError
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, redirect
from .forms import ContactForm
1 def emailView(request):
2 if request.method == 'GET':
3 form = ContactForm()
4 else:
5 form = ContactForm(request.POST)
6 if form.is_valid():
7 subject = form.cleaned_data['subject']
8 from_email = form.cleaned_data['from_email']
9 message = form.cleaned_data['message']
10 try:
11 send_mail(subject, message, from_email, ['admin@example.com'])
12 except BadHeaderError
13 return HttpResponse('ヘッダー情報が正しくありません.')
14 return redirect('success')
15 return render(request, "form.html", {'form': form})
16 def successView(request):
17 return HttpResponse('メールが送信されました。')
コードの解説(1) まずは2行目です。これはリクエストがgetの場合、すなわちurlpatternsに合致してはじめてこのメソッドが呼び出される場合の処理が書かれています。
getの場合は、form=ContactForm()として、空のフォームを返すようにしています。
この後、15行目が呼び出されるのですが、ここではform.html、すなわち同じhtmlファイルが呼び出されます。
(2) form.htmlが呼び出されるときはpostメソッドで呼び出されますので、5行目のコードが実行されます。
(3) 6行目のコードが実行され、フォームのバリデーションが行われます。バリデーションが無事に完了したら、メールを送るという形です。
(4) メール送信処理が完了したら、14行目のsuccessにリダイレクトされるようにしています。このsuccessは、urlpatternsで16行目のsuccessViewを呼び出していますので、結果として16行目が実行され、ブラウザ上に「メールが送信されました」という表示が出るようになるのです。
お問い合わせフォームのまとめ
(1) getメソッドかpostメソッドで処理を変えるのがポイント。
(2) class based viewでもfunction based viewでも実装することができる。
(3) formはContactFormクラスから作られたオブジェクトであることを意識する。