【Django】問い合わせフォームの実装

## はじめに

Django を使用して転職用のポートフォリオに問い合わせ機能を追加したので、備忘録としてこの記事を作成しました。どなたかの参考になれば嬉しいです。

---

## **実装**

### **1. プロジェクトとアプリの作成**

まず、Django プロジェクトと問い合わせアプリを作成します。

```bash
django-admin startproject inquiry_sample
cd inquiry_sample
python manage.py startapp contact
```

---

### **2. `settings.py` の設定**

#### **問い合わせアプリを追加**


```python: inquiry_sample/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'contact',  # 問い合わせアプリ
]
```

#### **メール送信の設定**

##### **Gmail を使用する場合**

```python: inquiry_sample/settings.py
# メール送信の設定
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "smtp.gmail.com"
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = "your_email@gmail.com"
EMAIL_HOST_PASSWORD = "your_app_password"
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
```

`EMAIL_HOST_PASSWORD` には **Gmail のアプリパスワード** を設定する必要があります。発行手順は以下のリンクを参考にしてください。

- [2024年最新版 - DjangoからGmailを送信](https://qiita.com/OzWay_jon/items/cf16429cd7f64ff8670d)
- [Gmail ヘルプ](https://support.google.com/mail/answer/185833?hl=ja)

##### **Outlook を使用する場合**

```python
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "smtp.office365.com"
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = "your_email@outlook.com"
EMAIL_HOST_PASSWORD = "your_app_password"
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
```

Outlook の **アプリパスワード** を使用する必要があります。取得方法は公式ヘルプを参照してください。

[Microsoft アプリパスワードの取得方法](https://support.microsoft.com/ja-jp/account-billing/%E3%82%A2%E3%83%97%E3%83%AA-%E3%83%91%E3%82%B9%E3%83%AF%E3%83%BC%E3%83%89%E3%82%92%E5%8F%96%E5%BE%97%E3%81%97%E3%81%A6%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95-5896ed9b-4263-e681-128a-a6f2979a7944)

---

### **3. `forms.py` の作成**

```python: contact/forms.py
from django import forms

class ContactForm(forms.Form):
    name = forms.CharField(label="お名前", max_length=100)
    email = forms.EmailField(label="メールアドレス")
    subject = forms.CharField(label="件名", max_length=100)
    message = forms.CharField(label="メッセージ", widget=forms.Textarea)
    send_copy = forms.BooleanField(label="自分にも送信する", required=False)
```

---

### **4. `views.py` の作成**


```python: contact/views.py
from django.shortcuts import render, redirect
from django.core.mail import EmailMessage
from django.http import HttpResponse
from django.conf import settings
from .forms import ContactForm

def contact_form(request):
    if request.method == "POST":
        form = ContactForm(request.POST)
        if form.is_valid():
            name = form.cleaned_data["name"]
            email = form.cleaned_data["email"]
            subject = form.cleaned_data["subject"]
            message = form.cleaned_data["message"]
            send_copy = form.cleaned_data["send_copy"]

            full_message = f"お名前: {name}\nメールアドレス: {email}\n\nメッセージ:\n{message}"
            recipients = [settings.EMAIL_HOST_USER]
            if send_copy:
                recipients.append(email)

            try:
                email_message = EmailMessage(
                    subject=subject,
                    body=full_message,
                    from_email=settings.EMAIL_HOST_USER,
                    to=recipients,
                    headers={"Reply-To": email},
                )
                email_message.send()
            except Exception as e:
                return HttpResponse(f"メール送信中にエラーが発生しました: {e}")

            return redirect("contact:complete")
    else:
        form = ContactForm()

    return render(request, "contact/contact_form.html", {"form": form})

def complete(request):
    return render(request, "contact/complete.html")
```

---

### **5. `urls.py` の設定**

#### **contact アプリの URL をプロジェクトのルートに設定**
```python: inquiry_sample/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path("admin/", admin.site.urls),
    path("", include("contact.urls")),
]
```


#### **contact_formとcompleteページのurlを設定**
```python: contact/urls.py
from django.urls import path
from . import views

app_name = "contact"

urlpatterns = [
    path("", views.contact_form, name="contact_form"),
    path("complete/", views.complete, name="complete"),
]
```

---

### **6. テンプレートの作成**

#### **問い合わせフォームのテンプレート**
```html: contact/templates/contact/contact_form.html
<h2>お問い合わせフォーム</h2>
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">送信</button>
</form>
```


#### **送信完了のテンプレート**
```html: contact/templates/contact/complete.html
<h2>お問い合わせありがとうございました。</h2>
<p>メッセージが送信されました。</p>
<a href="{% url 'contact:contact_form' %}">戻る</a>
```

---

### **7. 動作確認**

サーバーを起動し、`http://127.0.0.1:8000/` にアクセスしてフォームをテストします。

```bash
python manage.py runserver
```
 #### **問い合わせページにテスト情報を入力して送信**
![スクリーンショット 2025-03-16 102148.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952798/da2b15c3-ad35-47d2-950d-f0335376fe6b.png)

#### **送信が成功しました**
「送信完了」画面が表示され、フォームの送信処理が正常に完了しました。
![スクリーンショット 2025-03-16 102325.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952798/0ded385f-0734-4a46-a8f4-af8b129a32a7.png)

#### **Gmail でメールを確認**
問い合わせフォームで入力した情報がメールとして受信されました。受信者（サイト管理者）はフォームの内容を正しく確認できています。
![スクリーンショット 2025-03-16 102403.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952798/c09ad761-3835-4f63-a61f-9daa4f50d5e2.png)

#### **送信元もメールを確認**
送信者にも確認メールが届きましたが、Gmail の迷惑メールフォルダに分類されたようです...
![スクリーンショット 2025-03-16 102625.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952798/ebc924f3-c5f2-4ff0-8cb1-f6e80310deec.png)


---

## **まとめ**

Django を使って問い合わせフォームを実装しました。実際に運用する際は、エラーハンドリングやスパム対策も検討するとよいでしょう。

最後まで読んでいただき、ありがとうございました！ 

## **参考**
- [Qiita記事 : Django お問い合わせフォーム](https://qiita.com/yusuke_mrmt/items/ebefdb6e8704913f6a4c)
- [Django公式ドキュメント : メールを送信する](https://docs.djangoproject.com/ja/5.1/topics/email/)