Django 實作 聯絡我們


建立時間: 2022年6月9日 20:29
更新時間: 2022年6月10日 10:53

說明

使用 Django 前端設計聯絡我們頁
後端發送 Email 通知自己
在測試環境中,發送 Email 使用終端輸出模擬演示

正式環境發送 Email 會用 AWS Simple Email Service (SES)
到時會另外寫一篇文章來說明

這裡我使用傳統的 MTV 模式,做出簡易的畫面,並完成發信。

預覽

畫面大概會長這樣,非常陽春

截圖.png

settings

在 settings.py 設定

settings.py

# Console 輸出,本地測試用
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

forms

在你的應用程式的 forms.py 新增聯絡我們表單
這裡電話不過濾,如果有需要過濾可以參考 django-phonenumber-field
不過濾的原因是,電話是用來聯繫,沒有要發送簡訊驗證之類的用途,不會太嚴格要求
Email 過濾的原因是因為內建有提供,直接用就好
所以過濾取決於方不方便???

forms.py 一開始不會有這個檔案,如果沒有的話就在自己的 app 底下新增 forms.py 檔案
your_app/forms.py

表單範本,請依實際需求調整

forms.py

from django.forms import CharField
from django.forms import EmailField
from django.forms import Form
from django.forms import Textarea

class ContactForm(Form):
    """聯絡我們表單
    """

    name = CharField(label='姓名', max_length=150)
    email_address = EmailField(label='信箱', max_length=150, required=False)
    # 不過濾
    phone_number = CharField(label='電話', max_length=20, required=False)
    message = CharField(label='內容', max_length=2000, widget=Textarea)

views.py

當驗證失敗 if not form.is_valid(),重新傳送 form = ContactForm(request.POST)
會一併把錯誤訊息傳到前端

BadHeaderError 例外,是怕有不懷好意的人亂加 Header 進去

send_mail() message 空白,改用 html_message 使用 html 代碼
如果你只想傳純文字,可以改用 message,移除 html_message
render_to_string() 取得 html_message 的內容
所有表單的資料用 form.cleaned_data['email_address'] 取得乾淨的資料

views.py

from django.core.mail import send_mail
from django.http import BadHeaderError
from django.http import HttpRequest
from django.http import HttpResponse
from django.shortcuts import redirect
from django.shortcuts import render
from django.template.loader import render_to_string

from your_app.forms import ContactForm


def contact(request: HttpRequest) -> HttpResponse:
    """聯絡我們

    Args:
        request (HttpRequest): Http 請求

    Returns:
        HttpResponse: Http 回應
    """

    if request.method == 'POST':
        form = ContactForm(request.POST)

        if not form.is_valid():
            return render(
                request,
                'contact.html',
                {
                    'form': form,
                }
            )

        subject = '聯絡我們'

        rendered_email = render_to_string(
            'contact_to_mail.html',
            {
                'email_address': form.cleaned_data['email_address'],
                'message': form.cleaned_data['message'],
                'name': form.cleaned_data['name'],
                'phone_number': form.cleaned_data['phone_number'],
            }
        )

        try:
            send_mail(
                subject=subject,
                message='',
                html_message=rendered_email,
                from_email='admin@example.com',
                recipient_list=['admin@example.com']
            )
        except BadHeaderError:
            return HttpResponse('Invalid header found.')

        return redirect('contact')

    form = ContactForm()

    return render(
        request,
        'contact.html',
        {
            'form': form,
        }
    )

url 路徑

urls.py

from django.urls import path
from . import views

urlpatterns = [
    path("contact", views.contact, name="contact"),
]

templates

這是要顯示在前端的,我們擷取重要片段
我有套 bootstrap 所以你會看到很多 bootstrap class
但這只是很基礎的切版而已
重點在這兩行

{% csrf_token %}
{{ form.as_p }}

csrf 就是防跨站請求偽造 (Cross-site request forgery) 安全用途加的
這裡就不詳細說明資訊安全的事情了,只需知道加這個是為了資訊安全就好

form 變數就是 views 傳過來的 ContactForm
我們可以很方便的用 form.as_p 來渲染出表單的 html

contact.html

    <main class="mt-2">
        <div class="container">
            <div class="row">
                <div class="col">
                    <h1>聯絡我們</h1>
                </div>
            </div>
            <div class="row mb-2">
                <div class="col">
                    <form method="post">
                        {% csrf_token %}
                        {{ form.as_p }}
                        <button type="submit" class="btn btn-primary">送出</button>
                    </form>
                </div>
            </div>
        </div>
    </main>

contact_to_mail.html 就是很陽春的 email 發信的模板
我在網路上有看到有些 email 模板是用 xhtml 格式
因為我這個很單純是想送到 gmail,經過測試後 gmail 可以正常顯示
如果你要寄到其他信箱,請注意相容性的問題

contact_to_mail.html

<!DOCTYPE html>
<html lang="zh-Hant-TW">
    <head>
        <title>聯絡我們</title>
    </head>
    <body>
        <p>
            {{ message }}
        </p>
        <p>
            <div>姓名: {{ name }}</div>
            <div>電話: {{ phone_number }}</div>
            <div>信箱: {{ email_address }}</div>
        </p>
    </body>
</html>

結果

當你送信後會看到類似結果如下

Subject 亂碼是因為我打中文被編碼成 base64 編碼
Subject 的 b? 後面 5L6G6IeqIEVuam95IOi7n+mrlOeahOiBr+e1oeaIkeWAkQ==?=
就是 base64 編碼
原本內容是: 來自 Enjoy 軟體的聯絡我們

看起來我收到一則來自霸霸的訊息

Content-Type: multipart/alternative;
...略...
MIME-Version: 1.0
Subject: =?utf-8?b?5L6G6IeqIEVuam95IOi7n+mrlOeahOiBr+e1oeaIkeWAkQ==?=
From: admin@example.com
To: admin@example.com
Date: Fri, 10 Jun 2022 02:36:57 -0000
...略...
Content-Type: text/html; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit

<!DOCTYPE html>
<html lang="zh-Hant-TW">
    <head>
        <title>聯絡我們</title>
    </head>
    <body>
        <p>
            你好我叫霸霸
        </p>
        <p>
            <div>姓名: 霸霸</div>
            <div>電話: 0988888888</div>
            <div>信箱: babababa88@gmail.com</div>
        </p>
    </body>
</html>
...略...

參考

觀看次數: 886
contactcontact medjangoemailme
按讚追蹤 Enjoy 軟體 Facebook 粉絲專頁
每週分享資訊技術

一杯咖啡的力量,勝過千言萬語的感謝。

支持我一杯咖啡,讓我繼續創作優質內容,與您分享更多知識與樂趣!