App下載

Python:如何使用 Django 發(fā)送電子郵件

陪你演戲 2021-09-10 11:47:02 瀏覽數(shù) (5185)
反饋

在本篇文章中,我們將介紹如何使用 Django 發(fā)送電子郵件。我們將介紹如何配置 Django SMTP 連接,如何為你的電子郵件提供商設(shè)置應(yīng)用程序密碼,以及如何通過(guò) Django shell 發(fā)送電子郵件。我們還將研究如何為你的 Django 應(yīng)用程序設(shè)置聯(lián)系表單,這將允許你的客戶與你聯(lián)系。

大多數(shù) Web 應(yīng)用程序使用電子郵件來(lái)管理關(guān)鍵操作,例如重置密碼、帳戶激活、接收客戶反饋、發(fā)送新聞通訊和營(yíng)銷活動(dòng)。這些任務(wù)中的大多數(shù)都需要像?SendGrid?或?Mailgun?這樣的專用服務(wù)。但是,如果你不希望你的網(wǎng)站獲得大量訪問(wèn)者,你實(shí)際上可以通過(guò)你的個(gè)人電子郵件提供商完成很多工作。

了解 SMTP

SMTP(或簡(jiǎn)單郵件傳輸協(xié)議)是一組用于確定電子郵件如何從發(fā)件人傳輸?shù)绞占说囊?guī)則。SMTP 服務(wù)器使用此協(xié)議來(lái)發(fā)送和中繼外發(fā)電子郵件。(請(qǐng)注意,其他協(xié)議管理電子郵件的接收方式。)

SMTP 服務(wù)器始終具有唯一的地址和用于發(fā)送消息的特定端口,在大多數(shù)情況下為587。我們將看到在使用 Django 發(fā)送電子郵件時(shí)端口是如何相關(guān)的。

由于我們將使用 Gmail,因此我們將使用的地址是?smtp.gmail.com?,端口是 ?587?。

現(xiàn)在讓我們看看如何使用 Django 發(fā)送電子郵件。

創(chuàng)建 Django 項(xiàng)目

每個(gè) Django 項(xiàng)目都應(yīng)該有一個(gè)虛擬環(huán)境,因?yàn)槲覀儾幌肱獊y項(xiàng)目依賴項(xiàng)。要?jiǎng)?chuàng)建一個(gè),請(qǐng)運(yùn)行以下命令:

python -m venv .venv

上面的命令創(chuàng)建了一個(gè)名為 的虛擬環(huán)境.venv。要激活此虛擬環(huán)境,您可以使用以下命令:

source .venv/bin/activate

由于 Django 是第三方包,你必須用 pip 安裝它:

pip install django

這將安裝最新版本的 Django,你可以使用pip freeze.

要?jiǎng)?chuàng)建 Django 項(xiàng)目,請(qǐng)調(diào)用命令行實(shí)用程序?django-admin?:

django-admin startproject EmailProject

使用上面的命令,你正在創(chuàng)建一個(gè)名為 的 Django 項(xiàng)目?EmailProject?,但你可以使用任何你想要的名稱創(chuàng)建該項(xiàng)目。

現(xiàn)在,進(jìn)入項(xiàng)目目錄并運(yùn)行服務(wù)器:

cd EmailProject
python manage.py runserver

運(yùn)行 Django 服務(wù)器后,在瀏覽器中訪問(wèn)http://localhost:8000。你將看到一個(gè)自動(dòng)生成的頁(yè)面,其中包含最新的 Django 發(fā)行說(shuō)明。

Django本地服務(wù)器

修改設(shè)置

你需要在發(fā)送電子郵件之前修改設(shè)置文件,因此讓我們使用以下命令找到該文件tree:

注意:為簡(jiǎn)單起見(jiàn),我們將僅使用 UNIX(macOS 或 Linux)系統(tǒng)命令。

tree

該tree命令輸出目錄的文件結(jié)構(gòu)。在這種情況下,由于我們沒(méi)有給它一個(gè)特定的目錄路徑,如果我們?cè)陧?xiàng)目的根文件夾中,我們將得到類似于以下的內(nèi)容:

├── EmailProject
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py

1 directory, 6 files

我們將在本教程中不斷修改的文件是?EmailProject?文件夾中的?settings.py? 。

?settings.py?包含您需要的所有項(xiàng)目配置,并允許你設(shè)置自定義變量。正如 Django 文檔所說(shuō),“設(shè)置文件只是一個(gè)帶有模塊級(jí)變量的 Python 模塊”。

讓我們看一下使用 Django 發(fā)送電子郵件所需的設(shè)置。打開(kāi)?EmailProject/settings.py?文件并將以下設(shè)置粘貼到文件底部:

# EmailProject/settings.py

# Bottom of the file
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = ''
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''

讓我們通過(guò)分析這些設(shè)置中的每一個(gè)來(lái)分解上面的代碼。

電子郵件后端

該?EMAIL_BACKEND?設(shè)置聲明后端我們的Django項(xiàng)目將使用與SMTP服務(wù)器連接。

此變量指向?smtp.EmailBackend?接收發(fā)送電子郵件所需的所有參數(shù)的類。我強(qiáng)烈建議你直接在Django 源代碼上查看類構(gòu)造函數(shù)。你可能會(huì)驚訝于這段代碼的可讀性。

注意:雖然這個(gè)類是默認(rèn)的??EMAIL_BACKEND??,但在 Django 設(shè)置中顯式被認(rèn)為是一個(gè)好習(xí)慣。

所有其他電子郵件設(shè)置將基于此?EmailBackend? 類的構(gòu)造函數(shù)。

電子郵件主機(jī)

該?EMAIL_HOST?設(shè)置指的是你將使用的 SMTP 服務(wù)器域。這取決于你的電子郵件提供商。下表列出了與三個(gè)常見(jiàn)提供商對(duì)應(yīng)的 SMTP 服務(wù)器主機(jī):

電子郵件提供商SMTP 服務(wù)器主機(jī)
Gmailsmtp.gmail.com
Outlook/Hotmailsmtp-mail.outlook.com
雅虎smtp.mail.yahoo.com

我們暫時(shí)將此設(shè)置留空,因?yàn)槲覀兩院髮⑹褂?.env?文件來(lái)避免硬編碼敏感密鑰或每個(gè)站點(diǎn)的配置。你永遠(yuǎn)不應(yīng)該將憑據(jù)直接設(shè)置到代碼中。

我們將使用?Django Environ?來(lái)解決這個(gè)問(wèn)題。

電子郵件端口

該?EMAIL_PORT?設(shè)置必須設(shè)置為?587 ?,因?yàn)樗谴蠖鄶?shù) SMTP 服務(wù)器的默認(rèn)端口。對(duì)于個(gè)人電子郵件提供商而言,情況仍然如此。

此端口與 TLS 加密一起使用,以確保電子郵件發(fā)送的安全性。

電子郵件使用 TLS

傳輸層安全(TLS) 是一種跨 Web 使用的安全協(xié)議,用于加密 Web 應(yīng)用程序 (Django) 和服務(wù)器 (SMTP 服務(wù)器) 之間的通信。

最初,我們將?EMAIL_USE_TLS?變量設(shè)置為?True?。這意味著 Django 將使用傳輸層安全連接到 SMTP 服務(wù)器并發(fā)送電子郵件。(對(duì)于個(gè)人電子郵件提供商,這是強(qiáng)制性的。)

電子郵件主機(jī)用戶

?EMAIL_HOST_USER?設(shè)置是你的個(gè)人電子郵件地址?,F(xiàn)在將其留空,因?yàn)槲覀儗⑹褂盟?django-environ?來(lái)設(shè)置所有這些憑據(jù)。

電子郵件主機(jī)密碼

?EMAIL_HOST_PASSWORD?設(shè)置是你將從你的電子郵件帳戶中獲得的應(yīng)用密碼 - 我們將在本節(jié)之后立即執(zhí)行此過(guò)程。

同樣:將此設(shè)置留空,因?yàn)槲覀兩院髮⑹褂铆h(huán)境變量。

在 Gmail 中設(shè)置應(yīng)用密碼

要使用?EMAIL_HOST_PASSWORD?設(shè)置,你需要激活安全性較低的應(yīng)用訪問(wèn)權(quán)限,并從你的個(gè)人電子郵件地址獲得應(yīng)用密碼。

如果你不激活安全性較低的應(yīng)用程序訪問(wèn)權(quán)限,你可能會(huì)得到一個(gè)?SMTPAuthenticationError?,因?yàn)?Django 無(wú)法遵守 Google 安全協(xié)議。

你可以選擇使用普通密碼,但這比使用應(yīng)用密碼風(fēng)險(xiǎn)更大。我的建議是創(chuàng)建一個(gè)新的 Gmail 帳戶或使用“測(cè)試”電子郵件地址。

考慮到這一點(diǎn),你可以通過(guò)以下步驟獲取?Gmail ?應(yīng)用密碼。請(qǐng)注意,如果你使用的是現(xiàn)有帳戶并啟用了兩步驗(yàn)證,則可以跳過(guò)第 2 步和第 3 步:

  1. 創(chuàng)建或登錄 Gmail 帳戶
  2. 轉(zhuǎn)到myaccount.google.com/lesssecureapps并打開(kāi)安全性較低的應(yīng)用程序選項(xiàng)。不太安全的應(yīng)用
  3. 啟用雙因素身份驗(yàn)證,因?yàn)樾枰@取應(yīng)用密碼。2 因素驗(yàn)證
  4. 現(xiàn)在你已啟用雙因素身份驗(yàn)證,是時(shí)候獲取應(yīng)用密碼了。為此,你可以轉(zhuǎn)到Google 帳戶的安全部分,向下滾動(dòng)到登錄 Google 部分,然后點(diǎn)擊應(yīng)用密碼。

應(yīng)用密碼


在被重定向到應(yīng)用程序密碼頁(yè)面之前,你需要重新提示您的密碼(帳戶密碼)。

進(jìn)入后,單擊?select app?,你將為該應(yīng)用程序密碼選擇一個(gè)自定義名稱 - 例如“?Django Send Email?” - 然后單擊?GENERATE?。

應(yīng)用密碼生成

將顯示一個(gè)新窗口,其中包含一個(gè) ?16? 個(gè)字符的密碼。復(fù)制它,因?yàn)槲覀冃枰鼇?lái)配置我們的 Django 項(xiàng)目。

生成的應(yīng)用密碼

使用 Django Environ 隱藏敏感鍵

即使你只是在開(kāi)發(fā)中發(fā)送電子郵件,也不應(yīng)該將密碼直接寫入源代碼。當(dāng)使用版本控制系統(tǒng)和 GitHub 來(lái)托管你的項(xiàng)目時(shí),這一點(diǎn)變得更加重要。你不希望人們?cè)L問(wèn)你的數(shù)據(jù)。

讓我們看看如何通過(guò)使用?Django-environ?來(lái)防止這種情況發(fā)生。

使用以下命令?.env?在?EmailProject?目錄(?settings.py?文件所在的位置)內(nèi)創(chuàng)建一個(gè)文件:

cd EmailProject/
ls

settings.py # The settings file must be here

touch .env

現(xiàn)在,打開(kāi)該?.env?文件并輸入以下鍵值對(duì):

EMAIL_HOST=smtp.gmail.com
EMAIL_HOST_USER=YourEmail@address
EMAIL_HOST_PASSWORD=YourAppPassword
RECIPIENT_ADDRESS=TheRecieverOfTheMails

分解此文件的內(nèi)容:

  • ?EMAIL_HOST?:你的電子郵件提供商 SMTP 服務(wù)器地址。請(qǐng)參閱上面的電子郵件主機(jī)表以獲取快速指導(dǎo)。在本例中,我使用的?smtp.gmail.com?是 Gmail SMTP 地址。
  • ?EMAIL_HOST_USER?:你的電子郵件地址。
  • ?EMAIL_HOST_PASSWORD?:你剛剛生成的應(yīng)用密碼。請(qǐng)記住,它不包含任何空格。
  • ?RECIPIENT_ADDRESS?:你將收到郵件的電子郵件地址。這是我們稍后將創(chuàng)建的自定義設(shè)置,用于將所有電子郵件發(fā)送給同一收件人。

要使用這些環(huán)境變量,我們需要安裝?Django-environ?:

pip install django-environ

注意:確保你的虛擬環(huán)境已激活。

現(xiàn)在,打開(kāi)?settings.py?位于?EmailProject?目錄中的 并使用以下代碼:

# EmailProject/settings.py
# This should be at the start of the file
import environ

env = environ.Env()
environ.Env.read_env()

# Previous settings ...
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = env('EMAIL_HOST')
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = env('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD')

# Custom setting. To email
RECIPIENT_ADDRESS = env('RECIPIENT_ADDRESS')

首先,我們?cè)?environ?設(shè)置文件的頂部導(dǎo)入包。請(qǐng)記住,所有導(dǎo)入都應(yīng)在開(kāi)頭。

然后我們創(chuàng)建一個(gè)?env?變量,該變量將包含?.env?.

?env('KEY')?語(yǔ)句意味著我們正在查找該鍵的值。確保?.env?在繼續(xù)之前設(shè)置了文件,因?yàn)槿绻?ImproperlyConfigured?未設(shè)置某些環(huán)境變量,你將收到 Django錯(cuò)誤。

請(qǐng)注意,這?RECIPIENT_ADDRESS?是一個(gè)自定義設(shè)置,我們將使用它來(lái)將電子郵件發(fā)送到我們可以訪問(wèn)的地址。

如果你使用 Git 和 GitHub .env,請(qǐng)不要忘記在?.gitignore?中包含該文件。你只需打開(kāi)它并添加以下行即可完成此操作:

.env

1. 使用 Django Shell 發(fā)送電子郵件

最后,我們進(jìn)入了文章的精彩部分!是時(shí)候向 Django 發(fā)送你的第一封電子郵件了。

打開(kāi)終端,激活虛擬環(huán)境,然后運(yùn)行:

python manage.py shell

這將創(chuàng)建一個(gè) shell,其中包含已為我們配置的所有 Django 設(shè)置。在那個(gè)全新的 shell 中,粘貼以下代碼:

>>> from django.core.mail import send_mail
>>> from django.conf import settings
>>> send_mail(
...     subject='A cool subject',
...     message='A stunning message',
...     from_email=settings.EMAIL_HOST_USER,
...     recipient_list=[settings.RECIPIENT_ADDRESS])
1

我們也可以在不指定參數(shù)的情況下制作單行:

>>> send_mail('A cool subject', 'A stunning message', settings.EMAIL_HOST_USER, [settings.RECIPIENT_ADDRESS])
1

讓我們分解上面的代碼:

  • 我們導(dǎo)入 Django ?send_mail?函數(shù)。
  • 然后我們導(dǎo)入settings包含所有全局設(shè)置和每個(gè)站點(diǎn)設(shè)置(settings.py文件內(nèi)的設(shè)置)的對(duì)象。
  • 最后,我們將所有需要的參數(shù)傳遞給?send_mail?函數(shù)。此函數(shù)返回發(fā)送的電子郵件數(shù)量,在本例中為1。

請(qǐng)注意我們?nèi)绾问褂胹ettings對(duì)象來(lái)獲取?from_email?(您用來(lái)發(fā)送電子郵件的電子郵件)和?recipient_list?(??我們?cè)?RECIPIENT_ADDRESS?中定義的自定義設(shè)置?.env?)。

現(xiàn)在,如果我檢查我的收件箱——當(dāng)我將?RECIPIENT_ADDRESS?環(huán)境變量設(shè)置為我的電子郵件地址時(shí)——我將收到 Django 發(fā)送的消息。

Django 發(fā)送電子郵件

2. 使用 Django 構(gòu)建自動(dòng)聯(lián)系表單

在本節(jié)中,我們將使用 Django 表單和內(nèi)置?send_mail?函數(shù)構(gòu)建一個(gè)自動(dòng)聯(lián)系表單。此外,我們將?send()?在聯(lián)系表單中創(chuàng)建一個(gè)自定義函數(shù) ,以便在視圖中更容易實(shí)現(xiàn)它。

讓我們從創(chuàng)建聯(lián)系人應(yīng)用程序開(kāi)始。進(jìn)入項(xiàng)目根目錄——所在?manage.py的?位置——并運(yùn)行:

python manage.py startapp contact

然后,將其安裝在文件?INSTALLED_APPS?內(nèi)的變量中?EmailProject/settings.py?:

# EmailProject/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    ...

    # Custom
    'contact',
]

在推進(jìn)contact應(yīng)用程序之前,讓我們配置文件的?urlpatterns?內(nèi)部?EmailProject/urls.py?。為此,請(qǐng)導(dǎo)入?django.urls.include?函數(shù)并在整個(gè)項(xiàng)目中包含聯(lián)系人 URL。別擔(dān)心;我們稍后將配置聯(lián)系人 URL:

# EmailProject/urls.py

from django.contrib import admin
from django.urls import path, include # New import

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('contact.urls')) # Include Contact URLs
]

聯(lián)系表

進(jìn)入contact應(yīng)用程序文件夾并創(chuàng)建一個(gè)?forms.py?文件。在?forms.py?文件中定義所有表單是一種很好的做法,但這不是強(qiáng)制性的。這就是 Django 默認(rèn)不包含這個(gè)文件的原因。

你可以使用以下命令創(chuàng)建表單文件:

cd ../contact/
# You were inside the EmailProject folder
touch forms.py

打開(kāi)你剛剛創(chuàng)建的文件并進(jìn)行以下導(dǎo)入:

# contact/forms.py
from django import forms
from django.conf import settings
from django.core.mail import send_mail

Django表單模塊為我們提供了創(chuàng)建聯(lián)系表單所需的所有類和字段。我們?cè)俅螌?dǎo)入?settings?對(duì)象和?send_mail?發(fā)送電子郵件的函數(shù)。

我們的聯(lián)系表單將包含多個(gè)字段并使用兩種自定義方法:?get_info()?,用于格式化用戶提供的信息,以及?send()?,將發(fā)送消息。

讓我們看看這在代碼中的實(shí)現(xiàn):

# contact/forms.py
class ContactForm(forms.Form):

    name = forms.CharField(max_length=120)
    email = forms.EmailField()
    inquiry = forms.CharField(max_length=70)
    message = forms.CharField(widget=forms.Textarea)

    def get_info(self):
        """
        Method that returns formatted information
        :return: subject, msg
        """
        # Cleaned data
        cl_data = super().clean()

        name = cl_data.get('name').strip()
        from_email = cl_data.get('email')
        subject = cl_data.get('inquiry')

        msg = f'{name} with email {from_email} said:'
        msg += f'\n"{subject}"\n\n'
        msg += cl_data.get('message')

        return subject, msg

    def send(self):

        subject, msg = self.get_info()

        send_mail(
            subject=subject,
            message=msg,
            from_email=settings.EMAIL_HOST_USER,
            recipient_list=[settings.RECIPIENT_ADDRESS]
        )

這是一個(gè)巨大的類,所以讓我們分解我們?cè)诿總€(gè)部分中所做的事情。首先,我們定義了發(fā)送消息所需的四個(gè)字段:

  • ?name?和?enquiry?是表示聯(lián)系消息的名稱和原因的?CharFields?。
  • ?email?是一個(gè)?EmailField?,代表試圖與您聯(lián)系的人的電子郵件??紤]到電子郵件不會(huì)由用戶的電子郵件地址發(fā)送,而是由您在 Django 項(xiàng)目中設(shè)置的發(fā)送電子郵件的電子郵件地址發(fā)送。
  • ?message?是另一個(gè)?CharField?例外,我們使用的是?Textarea?小部件。這意味著,當(dāng)顯示表單時(shí),它將呈現(xiàn)一個(gè)?<textarea>?標(biāo)簽而不是一個(gè)簡(jiǎn)單的?<input>?.

進(jìn)入自定義方法,我們只使用該?get_info?方法來(lái)格式化用戶提供的信息并返回兩個(gè)變量:?subject?,它只是?inquiry?字段,以及?message?,它將是 Django 發(fā)送的實(shí)際消息。

另一方面,該?send()?方法僅從函數(shù)中獲取格式化信息?get_info?并發(fā)送消息?send_mail?。

盡管本節(jié)非常大,但你將看到我們?nèi)绾瓮ㄟ^(guò)將所有發(fā)送邏輯實(shí)現(xiàn)到?ContactForm?自身來(lái)簡(jiǎn)化聯(lián)系人視圖。

聯(lián)系人視圖

打開(kāi)?contact/views.py?文件并添加以下導(dǎo)入:

# contact/views.py
from django.views.generic import FormView, TemplateView
from .forms import ContactForm
from django.urls import reverse_lazy

如你所見(jiàn),我們將使用Django 通用視圖,這在執(zhí)行簡(jiǎn)單任務(wù)時(shí)為我們節(jié)省了大量時(shí)間——例如,在?FormView?使用?TemplateView?.

此外,我們正在導(dǎo)入?ContactForm?我們?cè)谏弦还?jié)中構(gòu)建的 以及在使用基于類的視圖時(shí)使用的?reverse_lazy?函數(shù)。

繼續(xù)查看視圖,讓我們編寫?ContactView?:

# contact/views.py

class ContactView(FormView):
    template_name = 'contact/contact.html'
    form_class = ContactForm
    success_url = reverse_lazy('contact:success')

    def form_valid(self, form):
        # Calls the custom send method
        form.send()
        return super().form_valid(form)

如你所見(jiàn),我們正在使用我們創(chuàng)建的構(gòu)建一個(gè)簡(jiǎn)單的?FormView??ContactForm?。我們也在設(shè)置?template_name?和?success_url?。我們稍后將編寫 HTML 模板并設(shè)置 URL。

該形式有效的方法,讓我們用發(fā)送電子郵件?ContactForm.send()?只有在形式的所有字段都是有效的方法。這意味著如果用戶輸入無(wú)效的輸入——例如未格式化的電子郵件地址——消息將不會(huì)被發(fā)送。

?form_valid?在基于函數(shù)的視圖中,上述方法實(shí)現(xiàn)將等效于以下內(nèi)容:

# Previous function based contact_view ...

if request.method == 'POST':
    form = ContactForm(request.POST)
    if form.is_valid():
        form.send()
        return redirect('contact:success')
else:
    form = ContactForm())

在本節(jié)結(jié)束時(shí),我們將編寫一個(gè)?ContactSucessView?,它將向用戶顯示一條成功消息。由于我們已經(jīng)導(dǎo)入了?TemplateView?類,我們只需要繼承它并定義?template_name?屬性:

# contact/views.py
class ContactSuccessView(TemplateView):
    template_name = 'contact/success.html'

聯(lián)系網(wǎng)址

是時(shí)候創(chuàng)建contact應(yīng)用程序的 URL 模式了。由于 ?Djangourls.py?默認(rèn)不給我們文件,我們需要使用以下命令創(chuàng)建它(確保在?contactapp ?文件夾中):

pwd
# /path/to/project/EmailProject/contact
touch urls.py

打開(kāi)該文件并設(shè)置?app_name?和?urlpatterns?變量:

from django.urls import path
from .views import ContactView, ContactSuccessView

app_name = 'contact'

urlpatterns = [
    path('', ContactView.as_view(), name="contact"),
    path('success/', ContactSuccessView.as_view(), name="success"),
]

我們使用路徑將路由及其對(duì)應(yīng)視圖包含到應(yīng)用程序的 URL 配置中。當(dāng)我們將app_name變量設(shè)置為 時(shí)'contact',這意味著應(yīng)用程序的 URL命名空間將如下所示:

contact:name_of_path
# For ContactView
contact:contact
# For ContactSuccessView
contact:success

注意:命名空間是我們?cè)?Django 模板和視圖中動(dòng)態(tài)調(diào)用的 URL。

你可以在官方文檔中了解有關(guān) Django URL 調(diào)度程序的更多信息。

編寫模板

Django 模板是動(dòng)態(tài)顯示數(shù)據(jù)的首選方式,使用HTML和 Django 模板語(yǔ)言給我們的特殊標(biāo)簽。

對(duì)于這個(gè)特定的應(yīng)用程序,我們將使用三個(gè)模板:

  • ?base.html?: 所有其他模板都將從它繼承。它將包含所有模板必須具有的所有 HTML 框架,以及指向 Bootstrap 的鏈接。
  • ?contact.html?:顯示聯(lián)系表格。
  • ?success.html?: 顯示成功消息。

讓我們從創(chuàng)建聯(lián)系人的應(yīng)用程序模板結(jié)構(gòu)開(kāi)始(確保你在聯(lián)系人應(yīng)用程序文件夾中):

mkdir -p templates/contact/
cd templates/contact
touch base.html contact.html success.html

上面的命令創(chuàng)建了可重用 Django 應(yīng)用程序的典型模板結(jié)構(gòu)?appname/templates/appname?——以及我之前提到的樹(shù)模板文件。

應(yīng)用程序文件結(jié)構(gòu)現(xiàn)在應(yīng)該如下所示:

.
├── admin.py
├── apps.py
├── forms.py
├── __init__.py
├── migrations
│   └── __init__.py
├── models.py
├── templates
│   └── contact
│       ├── base.html
│       ├── contact.html
│       └── success.html
├── tests.py
├── urls.py
└── views.py

讓我們進(jìn)入?base.html?模板的內(nèi)容:

<!-- contact/templates/contact/base.html -->

<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Django Email Send</title>
    <link  rel="stylesheet"
      integrity="sha384-wEmeIV1mKuiNpC+IOBjI7aAzPcEZeedi5yW5f2yOq55WWLwNGmvvx4Um1vskeMj0" crossorigin="anonymous" />
  </head>

  <body>
    {% block body %}

    {% endblock %}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-p34f1UUtsS3wqzfto5wAAmdvj+osOnFyQFpp4Ua3gs/ZVWx6oOypYoCJhGGScy+8" crossorigin="anonymous">
    </script>
  </body>

</html>

如你所見(jiàn),它是包含Bootstrap 5鏈接的 HTML 文件的簡(jiǎn)單框架。這允許我們?cè)诓皇褂?CSS 文件的情況下對(duì)我們的聯(lián)系人應(yīng)用程序進(jìn)行風(fēng)格化。

{% block name-of-block %}?標(biāo)簽允許我們?cè)O(shè)置一個(gè)“子模板”將使用的占位符。使用此標(biāo)記使模板繼承成為一項(xiàng)簡(jiǎn)單的任務(wù)。

在進(jìn)入表單之前,你需要安裝Django 脆皮表單包,它允許我們輕松地對(duì)它們進(jìn)行樣式化:

pip install django-crispy-forms

再一次,?crispy_forms?是一個(gè) Django 應(yīng)用程序,我們需要將它包含在?INSTALLED_APPS?列表中:

# config/settings.py

INSTALLED_APPS = [
    ...

    # 3rd party apps
    'crispy_forms',

    # Custom apps
    'contact',
]

# Indicates the frontend framework django crispy forms use
CRISPY_TEMPLATE_PACK = 'bootstrap4'

我們使用 Bootstrap 4 的模板包,因?yàn)?Bootstrap 表單類在第 4 版和第 5 版之間兼容(在撰寫本文時(shí))。

現(xiàn)在,讓我們處理?contact.html?模板:

<!-- contact/templates/contact/contact.html -->

{% extends 'contact/base.html' %}
{% load crispy_forms_tags %}

{% block body %}
<div class="mx-auto my-4 text-center">
    <h1>Contact Us</h1>
</div>
<div class="container">
    <form action="" method="post">
        {% csrf_token %}
        {{ form | crispy }}
    <button class="btn btn-success my-3" type="submit">Send message</button>
    </form>
</div>
{% endblock %}

請(qǐng)注意我們?nèi)绾螖U(kuò)展基本模板并使用塊占位符。這就是 Django 模板語(yǔ)言如此高效的原因,因?yàn)樗屛覀児?jié)省了大量的 HTML 復(fù)制和粘貼。

談到表單,我們使用了方法"?post?",這意味著我們ContactView將處理用戶提供的數(shù)據(jù),如果表單有效,我們將發(fā)送電子郵件。

{% csrf_token %}?是由于安全原因,所有形式的強(qiáng)制性。Django 的文檔有一個(gè)關(guān)于CSRF 令牌的專用頁(yè)面以及在處理表單時(shí)使用它們的原因。

我們將使用crispy模板標(biāo)簽渲染表單,這就是為什么我們用?{% load crispy_forms_tags %}?.

最后,讓我們編寫?success.html?模板:

{% extends 'contact/base.html' %}

{% block body %}
<div class="mx-auto my-4 text-center">
    <h1 class="fw-bolder text-success">We sent your message</h1>
    <p class="my-5">You can send another in the <a href="{% url 'contact:contact' %}">contact page</a></p>
</div>
{% endblock %}

如你所見(jiàn),這是一個(gè)簡(jiǎn)單的成功公告,其中包含指向聯(lián)系表單的鏈接,以防用戶想要發(fā)送另一條消息。

讓我們?cè)俅芜\(yùn)行服務(wù)器并訪問(wèn)http://localhost:8000(確保你已?.venv?激活并且你在項(xiàng)目根文件夾中):

python manage.py runserver

下圖顯示了最終聯(lián)系表格的樣子。

聯(lián)系表

這是成功消息的圖像。

成功訊息

這是收件箱中電子郵件的圖像。

收件箱

總結(jié)

恭喜!你已經(jīng)學(xué)習(xí)了如何使用 Django 發(fā)送電子郵件以及如何構(gòu)建 Django 聯(lián)系表單。

使用 Django 發(fā)送電子郵件的方法有很多種。在本教程中,你已使用個(gè)人電子郵件地址完成此操作,但我希望你探索其他工具并將它們集成到你的項(xiàng)目中。

在本篇文章中,我們介紹了以下內(nèi)容:

  • 如何設(shè)置 Django 設(shè)置以提供電子郵件
  • 小項(xiàng)目中如何使用個(gè)人郵箱發(fā)送郵件
  • 如何.env在 Django 項(xiàng)目中使用文件來(lái)使用敏感數(shù)據(jù)
  • 如何構(gòu)建自動(dòng)聯(lián)系表單


1 人點(diǎn)贊