Thành phần Email của Django
Django cung cấp một mô-đun mạnh mẽ để gửi email, hỗ trợ nhiều cấu hình khác nhau từ máy chủ SMTP truyền thống đến các backend email cục bộ hoặc dựa trên file. Để tích hợp khả năng gửi email vào ứng dụng Django, bạn cần cấu hình các thiết lập cơ bản và sử dụng hàm gửi email của framework.
Cấu hình Email trong settings.py
Trước khi gửi email, bạn cần định nghĩa các thông số kết nối SMTP trong file settings.py của dự án. Mặc định, Django sử dụng django.core.mail.backends.locmem.EmailBackend (lưu trữ email trong bộ nhớ, không gửi đi thật). Để gửi email qua máy chủ SMTP, bạn cần thay đổi backend và cung cấp thông tin chi tiết về máy chủ:
# Chỉ định backend email sử dụng giao thức SMTP
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
# Địa chỉ máy chủ SMTP (ví dụ: smtp.gmail.com, smtp.outlook.com)
EMAIL_HOST = 'smtp.ten-mien-cua-ban.com'
# Cổng của máy chủ SMTP (thường là 25, 465 cho SSL, hoặc 587 cho TLS)
EMAIL_PORT = 587 # Hoặc 25, 465 tùy thuộc vào cấu hình máy chủ của bạn
# Tên người dùng email (địa chỉ email dùng để đăng nhập)
EMAIL_HOST_USER = 'dia-chi-email-cua-ban@ten-mien.com'
# Mật khẩu ứng dụng hoặc mật khẩu tài khoản email của bạn
# Lưu ý: Sử dụng mật khẩu ứng dụng nếu dịch vụ email của bạn hỗ trợ để tăng cường bảo mật.
EMAIL_HOST_PASSWORD = 'MatKhauEmailCuaBan'
# Kích hoạt kết nối TLS (Transport Layer Security) để mã hóa
EMAIL_USE_TLS = True # Hoặc EMAIL_USE_SSL = True nếu cổng là 465 và dịch vụ yêu cầu SSL
# Tên hiển thị của người gửi (có thể trùng với EMAIL_HOST_USER)
DEFAULT_FROM_EMAIL = 'Tên Ứng Dụng <dia-chi-email-cua-ban@ten-mien.com>'
Gửi Email Cơ bản
Để gửi một email đơn giản, bạn có thể sử dụng hàm send_mail từ mô-đun django.core.mail. Hàm này cho phép bạn gửi cả email dạng văn bản thuần túy và email HTML.
from django.core.mail import send_mail
from django.conf import settings # Để truy cập các thiết lập từ settings.py
def gui_thong_bao_email(tieu_de, noi_dung_van_ban, danh_sach_nguoi_nhan, noi_dung_html=None):
"""
Gửi email thông báo cho một hoặc nhiều người nhận.
Args:
tieu_de (str): Tiêu đề của email.
noi_dung_van_ban (str): Nội dung email dạng văn bản thuần túy.
danh_sach_nguoi_nhan (list): Danh sách các địa chỉ email người nhận.
noi_dung_html (str, optional): Nội dung email dạng HTML. Mặc định là None.
"""
try:
so_email_da_gui = send_mail(
subject=tieu_de,
message=noi_dung_van_ban,
from_email=settings.DEFAULT_FROM_EMAIL,
recipient_list=danh_sach_nguoi_nhan,
html_message=noi_dung_html,
fail_silently=False, # Đặt True để bỏ qua lỗi khi gửi email
)
print(f"Đã gửi {so_email_da_gui} email thành công.")
except Exception as e:
print(f"Lỗi khi gửi email: {e}")
# Ví dụ sử dụng:
# tieu_de_moi = "Thông báo đơn hàng mới"
# noi_dung_text = "Bạn có một đơn hàng mới từ khách hàng ABC. Vui lòng kiểm tra."
# danh_sach_gui = ["nguoi_nhan_1@example.com", "nguoi_nhan_2@example.com"]
# noi_dung_html = "<h2>Chi tiết Đơn hàng</h2><p>Đơn hàng #123 đã được đặt thành công.</p>"
# gui_thong_bao_email(tieu_de_moi, noi_dung_text, danh_sach_gui, noi_dung_html)
Gửi Email Bất đồng bộ (Sử dụng Thread)
Để tránh làm chậm phản hồi của ứng dụng khi gửi email (quá trình này có thể tốn thời gian), bạn nên gửi email trong một luồng (thread) riêng biệt. Điều này giúp tiến trình chính của ứng dụng không bị chặn.
from django.core.mail import send_mail
from django.conf import settings
from threading import Thread
def gui_email_trong_luong(tieu_de, noi_dung, nguoi_gui, nguoi_nhan_list, html_message=None):
"""
Hàm đóng gói việc gửi email để chạy trong một luồng riêng.
"""
try:
send_mail(
subject=tieu_de,
message=noi_dung,
from_email=nguoi_gui,
recipient_list=nguoi_nhan_list,
html_message=html_message,
fail_silently=False,
)
print(f"Email '{tieu_de}' đã được gửi trong luồng thành công.")
except Exception as e:
print(f"Lỗi khi gửi email trong luồng: {e}")
# Ví dụ gọi hàm gửi email trong một luồng mới:
# tieu_de_cap_nhat = "Cập nhật quan trọng"
# noi_dung_cap_nhat = "Hệ thống vừa được nâng cấp. Vui lòng kiểm tra các tính năng mới."
# danh_sach_nhan = ["admin@example.com"]
# html_thong_bao = "<p>Xin chào Admin,</p><p>Hệ thống đã được cập nhật thành công.</p>"
# tao_luong_gui_email = Thread(
# target=gui_email_trong_luong,
# args=(tieu_de_cap_nhat, noi_dung_cap_nhat, settings.DEFAULT_FROM_EMAIL, danh_sach_nhan),
# kwargs={"html_message": html_thong_bao}
# )
# tao_luong_gui_email.start()
Thành phần Messages của Django
Thành phần Messages của Django là một framework cho phép bạn hiển thị các thông báo "một lần" cho người dùng. Các thông báo này thường được tạo trong một hàm view, sau đó được truyền qua một lần chuyển hướng (redirect) hoặc hiển thị ngay trong template, và biến mất sau khi được hiển thị. Chức năng này rất hữu ích khi bạn muốn thông báo kết quả của một hành động (ví dụ: "Lưu thành công", "Xóa thất bại") sau khi người dùng được chuyển hướng đến một trang khác.
Mặc dù các tác vụ tương tự có thể được thực hiện bằng AJAX trong các ứng dụng web hiện đại, hệ thống Messages của Django vẫn rất tiện lợi cho các ứng dụng dựa trên luồng request-response truyền thống hoặc khi bạn cần thông báo nhanh chóng mà không cần tái tải trang một phần.
Các cấp độ thông báo
Hệ thống Messages hỗ trợ nhiều cấp độ để phân loại và định dạng các thông báo khác nhau:
DEBUG: Thông báo gỡ lỗi, thường không hiển thị cho người dùng cuối.INFO: Thông tin chung, không quá quan trọng nhưng vẫn hữu ích.SUCCESS: Hành động được thực hiện thành công.WARNING: Cảnh báo về một vấn đề tiềm ẩn hoặc hành động không mong muốn.ERROR: Lỗi nghiêm trọng xảy ra, hành động thất bại.
Bạn có thể chọn cấp độ phù hợp tùy theo ngữ cảnh của thông báo.
Cấu hình Thành phần Messages
Để sử dụng hệ thống Messages, bạn cần đảm bảo các cấu hình sau có trong file settings.py của mình:
# 1. Cấu hình nơi lưu trữ messages.
# SessionStorage là lựa chọn phổ biến, lưu trữ trong session của người dùng.
# CookieStorage lưu trữ trong cookie (giới hạn kích thước).
# FallbackStorage thử CookieStorage trước, nếu không đủ chỗ thì chuyển sang SessionStorage.
MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
# 2. Thêm 'django.contrib.messages' vào danh sách INSTALLED_APPS
INSTALLED_APPS = [
# ... các ứng dụng khác của bạn
'django.contrib.messages',
# ...
]
# 3. Thêm MessageMiddleware vào danh sách MIDDLEWARE
MIDDLEWARE = [
# ... các middleware khác
'django.contrib.sessions.middleware.SessionMiddleware', # Cần thiết cho SessionStorage
'django.contrib.messages.middleware.MessageMiddleware',
# ...
]
# 4. Đảm bảo 'django.contrib.messages.context_processors.messages' có trong TEMPLATES
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
# ... các context processors khác
'django.contrib.messages.context_processors.messages',
],
},
},
]
Thêm Thông báo từ View
Trong một hàm view, bạn có thể dễ dàng thêm thông báo bằng cách sử dụng module django.contrib.messages:
from django.contrib import messages
from django.shortcuts import render, redirect
from .forms import MauFormSanPham # Giả định bạn có một form
def xu_ly_san_pham(request):
"""
View xử lý việc thêm hoặc cập nhật sản phẩm.
"""
if request.method == 'POST':
form = MauFormSanPham(request.POST)
if form.is_valid():
form.save()
messages.success(request, 'Sản phẩm đã được lưu thành công!')
return redirect('trang_danh_sach_san_pham') # Chuyển hướng đến trang danh sách
else:
messages.error(request, 'Có lỗi xảy ra khi lưu sản phẩm. Vui lòng kiểm tra lại dữ liệu.')
else:
form = MauFormSanPham()
return render(request, 'trang_sua_san_pham.html', {'form': form})
def xoa_san_pham(request, san_pham_id):
"""
View xử lý việc xóa một sản phẩm.
"""
try:
# Giả định logic xóa sản phẩm
# SanPham.objects.get(id=san_pham_id).delete()
messages.info(request, f'Sản phẩm ID {san_pham_id} đã được xóa.')
except Exception:
messages.warning(request, f'Không thể xóa sản phẩm ID {san_pham_id}. Có thể không tồn tại.')
return redirect('trang_danh_sach_san_pham')
Bạn cũng có thể sử dụng messages.add_message(request, level, message) để thêm thông báo với cấp độ tùy chỉnh:
from django.contrib import messages
# Thêm một thông báo thành công
messages.add_message(request, messages.SUCCESS, "Dữ liệu đã được cập nhật thành công!")
# Thêm một thông báo lỗi
messages.add_message(request, messages.ERROR, "Tác vụ không thể hoàn thành do lỗi hệ thống.")
Hiển thị Thông báo trong Template
Nhờ django.contrib.messages.context_processors.messages, biến messages sẽ tự động có sẵn trong ngữ cảnh của mọi template. Bạn có thể lặp qua nó để hiển thị tất cả các thông báo:
{% if messages %}
<ul class="messages-list">
{% for thong_bao in messages %}
<li class="alert alert-{{ thong_bao.tags }}">
{{ thong_bao }}
</li>
{% endfor %}
</ul>
{% endif %}
Ở đây, thong_bao.tags sẽ trả về chuỗi đại diện cho cấp độ thông báo (ví dụ: "success", "error", "warning"), có thể dùng làm class CSS để định kiểu cho thông báo. {{ thong_bao }} sẽ hiển thị nội dung của thông báo.
Đọc Thông báo từ Code Python
Bạn cũng có thể đọc các thông báo đã được lưu trữ trực tiếp từ code Python bằng cách sử dụng get_messages. Việc này sẽ "tiêu thụ" các thông báo, tức là chúng sẽ không còn hiển thị sau đó nữa.
from django.contrib.messages.api import get_messages
def kiem_tra_thong_bao(request):
"""
Hàm ví dụ để đọc và in các thông báo từ request.
"""
danh_sach_thong_bao = get_messages(request)
if danh_sach_thong_bao:
print("Các thông báo hiện có:")
for tb in danh_sach_thong_bao:
print(f"- Cấp độ: {tb.level}, Tags: {tb.tags}, Nội dung: {tb}")
else:
print("Không có thông báo nào.")
# Sau khi đọc, các thông báo này sẽ bị xóa khỏi storage
Cơ chế hoạt động của Messages Framework
Hệ thống Messages hoạt động dựa trên các middleware và context processor để quản lý vòng đời của thông báo:
- Request Processing: Khi một yêu cầu HTTP đến,
MessageMiddlewaresẽ tải các thông báo đã lưu trữ từ storage (session hoặc cookie) vào đối tượngrequest. - View Execution: Trong view, khi bạn gọi
messages.add_message()hoặc các hàm tắt nhưmessages.success(), thông báo mới sẽ được thêm vào một danh sách tạm thời trong đối tượngrequest. - Template Rendering: Nếu bạn đang hiển thị template,
messages.context_processors.messagessẽ đảm bảo rằng các thông báo (cũ và mới) được chuyển vào ngữ cảnh template dưới biếnmessages. Khi bạn lặp qua và hiển thị chúng, chúng được đánh dấu là "đã sử dụng". - Response Processing: Trước khi phản hồi được gửi đi,
MessageMiddlewaresẽ kiểm tra các thông báo. Nếu có thông báo mới hoặc thông báo cũ chưa được sử dụng, chúng sẽ được lưu lại vào storage (session/cookie) cho yêu cầu tiếp theo. Nếu tất cả thông báo đã được sử dụng, chúng sẽ bị xóa khỏi storage.