【Python】ふと、お問い合わせフォームを作りたくなったら

はじめまして。
普段はWebサービスの開発をしてます。

# はじめに
先日、ふと、**お問合わせフォーム**を用意したくなり、
さらに、その内容を自身の**メールアドレス宛に送信**したくなったので、
**Python**で実装しました。

# 全体像
本記事では、**Django**を使用します。
Djangoとても便利です。

![本文を追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259302/47591d4a-cd5a-26fd-a278-8423cf5f35dd.png)



# フォーム定義
フォーム定義は`forms.py`で行います。

基本的には、**Django標準機能**をインポートして作ります。

加えて、**フォームの項目**を定義します。
「名前」、「連絡先」、「お問い合わせ内容」みたいなやつですね。
各項目の必須設定や文字制限も定義できます。

<details><summary>サンプルコード</summary><div>

```python
# Django標準機能を import
from django import forms
from django.core.mail import BadHeaderError, send_mail
from django.http import HttpResponse
# Django設定をimport
from django.conf import settings


class ContactForm(forms.Form):
    # フォーム項目として"お名前"を定義
    name = forms.CharField(
        label='',
        max_length=100,
        widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': "お名前",
        }),
    )
    # フォーム項目として"メールアドレス"を定義
    email = forms.EmailField(
        label='',
        widget=forms.EmailInput(attrs={
            'class': 'form-control',
            'placeholder': "メールアドレス",
        }),
    )
    # フォーム項目として"お問い合わせ内容"を定義
    message = forms.CharField(
        label='',
        widget=forms.Textarea(attrs={
            'class': 'form-control',
            'placeholder': "お問い合わせ内容",
        }),
    )

    # メールを送信する
    def send_email(self):
        subject = "お問い合わせ"
        message = self.cleaned_data['message']
        name = self.cleaned_data['name']
        email = self.cleaned_data['email']
        from_email = '{name} <{email}>'.format(name=name, email=email)
        # 受信者リストを指定
        recipient_list = [settings.EMAIL_HOST_USER]
        try:
            send_mail(subject, message, from_email, recipient_list)
        except BadHeaderError:
            return HttpResponse("無効なヘッダが検出されました。")
```
</div></details>

# 処理定義
処理の定義は`views.py`で行います。

こちらも、**Django標準機能**をインポートして作ります。

加えて、上記のフォーム定義もインポートします。
また、**表示させる HTML**や**遷移する URL**などを指定します。

<details><summary>サンプルコード</summary><div>

```python
# Django標準機能をimport
from django.urls import reverse_lazy
from django.views.generic import TemplateView
from django.views.generic.edit import FormView

# forms.py からフォーム定義をimport
from .forms import ContactForm

# submitイベントの挙動を定義
class ContactFormView(FormView):
    # 表示させる html を指定
    template_name = 'contact_form.html'
    # form.py で定義したクラス名を指定
    form_class = ContactForm
    # 遷移後のurlを引数で指定
    success_url = reverse_lazy('contact_result')

    # メールを送信
    def form_valid(self, form):
        form.send_email()
        return super().form_valid(form)

# フォーム送信後の挙動を定義
class ContactResultView(TemplateView):
    # 表示させる html を指定
    template_name = 'contact_result.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['success'] = "お問い合わせは正常に送信されました。"
        return context
```
</div></details>


# 画面定義
お問い合わせ画面 と お問い合わせ送信後の画面 を用意します。

お問い合わせ画面では`{{ form.as_p }}`を使って、
フォーム定義で定義した項目を`<p>`タグでレンダリングします。

<details><summary>お問い合わせ画面</summary><div>

```html:contact_form.html
<h4>お問い合わせ</h4>
  <div>
    <p><br>必要事項を入力して下さい。</p>
    <form method="POST">{% csrf_token %}
      {{ form.as_p }}
      <button type="submit" class="btn">送信</button>
      <a href="{% url 'top' %}">トップに戻る</a>
    </form>
  </div>
</div>
```
</div></details>


<details><summary>お問い合わせ送信後の画面</summary><div>

```html:contact_result.html
<div>
  <p>
    お問い合わせ　送信完了
  </p>
  <div>
    <p>
      お問い合わせありがとうございました。<br>
      内容を確認のうえ、回答させて頂きます。
    </p>
    <a href="{% url 'top' %}">トップに戻る</a>
  </div>
</div>
```
</div></details>


# URL定義
`urls.py`で **URL と処理の紐付け**を定義します。

<details><summary>サンプルコード</summary><div>

```python
# 処理クラスをimport
# <PROJECT_NAME>は自身のプロジェクト名
from <PROJECT_NAME>.views import ContactFormView, ContactResultView

urlpatterns = [
    # ...
    path('contact/', ContactFormView.as_view(), name='contact_form'),
    path('result/', ContactResultView.as_view(), name='contact_result'),
]
```
</div></details>


# メール情報定義
最後に、`settings.py` でプログラムで使用する**メール情報**を定義します。
SMTPサーバーやポート番号、ユーザー情報を指定します。

<details><summary>サンプルコード</summary><div>

```python
EMAIL_HOST = 'smtp.XXX.com'
EMAIL_PORT = XXX
EMAIL_HOST_USER = 'XXX@XXX.com'
EMAIL_HOST_PASSWORD = 'XXX'
EMAIL_USE_TLS = True
```
</div></details>


# まとめ
Django標準機能を使用することで、簡単にお問い合わせフォームが作成できました。
ふと、お問い合わせフォームを作りたくなった時の参考になれば幸いです。