Django お問い合わせフォーム

#前提
Gmailのみ
※Gmailを使った実装については後日記述いたします。

Djangoインストール済み

プロジェクト名：sample
アプリ名：contact

#本題
早速実装していきます。

Djangoをインストールしたら、プロジェクトを作成します。

```
$ django-admin startproject project
```


cdコマンドで<code>project</code>ディレクトリに移動したら、アプリのディレクトリを作成します。


```
$ python3 manage.py startapp contact
```


<code>settings.py</code>を修正していきます。

```sample/project/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'contact', #追記
]

LANGUAGE_CODE = 'ja' #変更
TIME_ZONE = 'Asia/Tokyo' #変更
```


<code>settings.py</code>と同じディレクトリにある<code>urls.py</code>にアプリが紐づくように編集します。


```sample/project/urls.py
from django.contrib import admin
from django.urls import path, include # 追記

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('contact.urls')), # 追記
]
```


次は<code>contact</code>ディレクトリ内を編集します。
新しく<code>urls.py</code>を作成し、URLパターンを記述します。

```sample/contact/urls.py
from django.urls import path
from . import views

app_name = 'contact'
urlpatterns = [
        path('', views.index, name='index'),
        path('contact_form/', views.contact_form, name='contact_form'),
        path('contact_form/contact/complete/', views.complete, name='complete'),
]
```

テンプレートと紐づけるためにcontacディレクトリ内の<code>views.py</code>を編集します。

```sample/contact/views.py
from django.shortcuts import render


def index(request):
    return render(request, 'contact/index.html')

# お問い合わせフォーム画面
def contact_form(request):
    return render(request, 'contact/contact_form.html')

# 送信完了画面
def complete(request):
    return render(request, 'contact/complete.html')
```

続いてテンプレートの作成です。
contactディレクトリ内に新しく<code>templates</code>というディレクトリ（フォルダ）を作成し、
templatesディレクトリ内に**contactディレクトリ**を作成し、
contactディレクトリ内に<code>index.html</code>を作成していきます。

```sample/contact/templates/contact/index.html
<!doctype html>
<html>
  <head>
    <title>Webサイト</title>
  </head>
  <body>

<center>
<a href="{% url 'contact:contact_form' %}">
<h2>お問い合わせフォーム</h2>
</a>
</center>
</body>
</html>
```

続いてお問い合わせフォームです。

```sample/contact/templates/contact/contact_form.html
<center>
<h1>入力フォーム</h1><hr><br>
</center>
```

送信完了画面です。

```sample/contact/templates/contact/complete.html
<center>
<h1>送信完了</h1>
<a href="{% url 'contact:index' %}">
<p>トップへ</p>
</a>
</center>
```

##フォームの作成

DjangoのFormクラスを使ってテンプレートを表示させます。
contactディレクトリ内に新しく<code>forms.py</code>を作成します。

```sample/contact/forms.py
from django import forms

class ContactForm(forms.Form):
    subject = forms.CharField(label='件名', max_length=100)
    sender = forms.EmailField(label='Email', help_text='※ご確認の上、正しく入力してください。')
    message = forms.CharField(label='メッセージ', widget=forms.Textarea)
    myself = forms.BooleanField(label='同じ内容を受け取る', required=False)
```

■subject：件名
■sender：Eメール入力
■help_text：後にテンプレートで表示される注意書き。
■message：書き込む内容、<code>widget=forms.Textarea</code>とすることで
 複数行書き込めるテキストボックスが渡されます。
■myself：チェックボックス。


作成したContactFormを<code>views.py</code>の<code>contact_form</code>で処理し、
テンプレートに表示できるようにします。

```sample/contact/views.py
from django.shortcuts import render, redirect # 追記
from .forms import ContactForm # 追記

........
........
def contact_form(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            return redirect('contact:complete')
    else:
        form = ContactForm()
    return render(request, 'contact/contact_form.html', {'form': form})
.........
.........
```

<code>POST</code>されたフォームの内容を<code>form.is_valid()</code>で検証し正しければ
<code>complete.html</code>に渡されるという記述です。


次に表示するための記述をしていきます。
<code>contact_form.html</code>を編集します。

```sample/templates/contact/contact_form.html
<center>
<h1>入力フォーム</h1><hr><br>

<!--追記-->
<form action="{% url 'contact:contact_form' %}" method="post">
    {% csrf_token %}
<table>
    {{ form.as_table }}
</table><br>
    <input type="submit" value="送信">
</form>
</center>
```
<code>{% csrf_token %}</code>はクロスサイトリクエストフォージェリ (CSRF) 対策。
これがないとエラーになってしまいます。

Gmailについては後日記述いたします。