Khi phát triển module người dùng trong ứng dụng Django như hệ thống thương mại điện tử, việc kiểm soát dữ liệu địa chỉ một cách linh hoạt là yếu tố then chốt. Thay vì phụ thuộc hoàn toàn vào bộ quản lý mặc định objects, ta có thể xây dựng lớp quản lý tùy chỉnh kế thừa từ models.Manager để mở rộng chức năng truy vấn.
Ví dụ, để luôn lấy được địa chỉ mặc định của người dùng mà không cần lặp lại logic kiểm tra is_default=True ở nhiều nơi, ta định nghĩa lớp UserAddressManager:
from django.db import models
class UserAddressManager(models.Manager):
"""Quản lý địa chỉ người dùng với logic lấy địa chỉ mặc định"""
def get_primary_address(self, user_instance):
"""Trả về địa chỉ được đánh dấu là chính (default) cho người dùng"""
return self.filter(
user=user_instance,
is_default=True
).first() # .first() an toàn hơn .get() khi không tồn tại bản ghi
def get_all_by_user(self, user_instance):
"""Lấy danh sách tất cả địa chỉ theo thứ tự ưu tiên: default trước"""
return self.filter(user=user_instance).order_by('-is_default', '-update_time')
Sau đó gắn lớp quản lý này vào mô hình Address:
class Address(BaseModel):
user = models.ForeignKey('User', on_delete=models.CASCADE, related_name='addresses')
receiver = models.CharField(max_length=120, verbose_name='Người nhận')
address = models.CharField(max_length=400, verbose_name='Địa chỉ')
zip_code = models.CharField(max_length=6, null=True, verbose_name='Mã bưu chính')
phone = models.CharField(max_length=11, verbose_name='Số điện thoại')
is_default = models.BooleanField(default=False, verbose_name='Là địa chỉ mặc định')
objects = UserAddressManager()
Trong view xử lý trang cá nhân, việc lấy địa chỉ ưu tiên trở nên ngắn gọn và rõ ràng:
def profile_view(request):
context = {'type': 'profile'}
primary_addr = Address.objects.get_primary_address(request.user)
context['primary_address'] = primary_addr
context['all_addresses'] = Address.objects.get_all_by_user(request.user)
return render(request, 'user/profile.html', context)
Để nâng cao hiệu năng truy xuất dữ liệu thường xuyên như lịch sử xem sản phẩm, ta tích hợp Redis làm tầng cache thông qua gói django-redis. Đây là giải pháp chuẩn được cộng đồng Django khuyến nghị, hỗ trợ đầy đủ tính năng như cache, session backend và kết nối pool.
Cài đặt:
pip install django-redis
Cấu hình trong settings.py:
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/2',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
'CONNECTION_POOL_KWARGS': {'max_connections': 20},
}
}
}
Trong view hoặc service xử lý lịch sử duyệt hàng, ta sử dụng hàm tiện ích get_redis_connection thay vì khởi tạo kết nối thủ công:
from django_redis import get_redis_connection
def get_browsing_history(user_id, limit=5):
redis_conn = get_redis_connection('default')
history_key = f'browse_history:{user_id}'
# Lấy danh sách ID sản phẩm gần đây nhất
product_ids = redis_conn.lrange(history_key, 0, limit - 1)
# Loại bỏ trùng lặp và đảm bảo thứ tự
product_ids = list(dict.fromkeys(product_ids))
# Truy vấn cơ sở dữ liệu chỉ với các ID đã có
return Product.objects.filter(id__in=product_ids).order_by(
'-id' if not product_ids else None
)
Phương pháp này giúp giảm tải CSDL, tăng tốc độ phản hồi và dễ dàng mở rộng quy mô hệ thống.