Quản lý subsite với django
Khi phát triển một website cho các hệ thống quản lý và thương mại, chắc hẳn mọi người sẽ gặp một bài toán như sau: "Ví dụ bạn xây dựng một website abc.com và muốn khi người dùng đăng ký với tên là xyz thì sẽ tự động tạo ra một site cho người dùng dưới dạng http://abc.com/xyz hoặc tên miền mà người dùng lựa chọn". Với bài toán như vậy chúng ta sẽ xây dựng website ra sao để có thể quản lý được các site con như vậy?
Đây là một bài toán mà nhiều người đã và đang giải quyết. Nếu sử dụng các hệ thống có sẵn như Joomla, Drupal, Wordpress hay Plone thì đã được hỗ trợ phần nào. Với Django thì bạn thực hiện bài toán đó như thế nào? Được truyền cảm hứng từ bài viết của pduyha (Cấu hình Apache với nhiều Django site), với cách làm trên thì mỗi lần tạo một site mới chúng ta phải restart lại Apache (hoặc có cách reload). Nhưng khi số lượng site lớn dần thì công đoạn đó sẽ mất thời gian đáng kể. Bên cạnh đó sẽ có sự lãng phí tài nguyên và tốn công cho việc nâng cấp.
Bài viết này sẽ cố gắng đưa ra một cách giải quyết khác để quản lý được các site con mà không ảnh hưởng đến Apache và tiết kiệm được không gian lưu trữ vì tất cả các site sẽ được chạy chung một mã nguồn, do vậy cũng thuận tiện cho việc sửa đổi và nâng cấp.
Ý tưởng của phương pháp này đó là chúng ta sẽ xử lý url của site trước khí trả về cho django xử lý. Ví dụ chúng ta có trang web http://abc.com, trang about có địa chỉ là http://abc.com/about. Giờ chúng ta muốn tạo một site còn là xyz và muốn khi vào địa chi http://abc.com/xyz/about thì sẽ ra trang thông tin của ông xyz. Vậy chúng ta phải làm sao phân biệt được url đó là của trang chính hay là của trang con? Đơn giản là chúng ta phải phân tích url để đưa ra quyết định. Có 2 việc chúng ta phải giải quyết
- Phân tích URL trước khi cho Django xử lý
- Quản lý thông tin site con
Về vấn đề quản lý thông tin của site con chúng ta có thể tận dụng luôn được đối tượng Site có sẵn của Django. Đối tượng này có 2 thông tin là domain và name. Ở đây chúng để phân biệt doamain và subsite, mình sẽ lưu subsite thêm ký tự / ở đầu. Ví dụ nếu một trang web là http://abc.com/xyz thì thông tin sẽ được lưu trong trường domain của Site là /xyz.
Việc tiếp theo là tạo một Middleware cho Django (tài liệu về Middleware có thể đọc tại đây). Chúng ta sẽ tạo một app với file middleware.py có nội dung như sau
{syntaxhighlighter brush: python;fontsize: 100; first-line: 1; }from django.conf import settings import re from django.contrib.sites.models import Site class MultiSiteMiddleware: def process_request(self, request): r = re.match("^/([^/]*)($|(/.*$))", request.path) found = False if r: possible_subsite = r.groups()[0] real_action = r.groups()[1] if len(real_action) > 0 and real_action[0] == '/': real_action = real_action[1:] sites = Site.objects.all() for site in sites: if site.domain[0] == '/': # neu duoc dang ky la subsite /subsite subsite = site.domain[1:] # Loai bo / o dau if subsite == possible_subsite: found = True break # thoi ra ngoai thoi, xg roi request.META['SUB_SITE'] = '' if found: request.path = '/%s' % real_action request.path_info = '/%s' % real_action # cho them mot so thong tin de su dung request.META['SUB_SITE'] = possible_subsite request.META['SUB_SITE_ID'] = site.id else: request.META['SUB_SITE'] = '' request.META['SUB_SITE_ID'] = 0{/syntaxhighlighter}
Như trong code, khi url có dạng /xyz/function1 thì chương trình sẽ nhận diện đây là site /xyz và chạy chức năng function1, cùng với đó là các thông số được thiết lập thêm trong biến request (SUB_SITE và SUB_SITE_ID) để giúp các ứng dụng biết là hiện tại đang ở site nào.
Chúng ta cũng sẽ phải khai báo middleware này lên trên cùng khi khai báo Middleware của Django để đảm bảo luôn được thực thi đầu tiên. Việc khai báo này sẽ được làm trong phần settings của Django
{syntaxhighlighter brush: python;fontsize: 100; first-line: 1; }MIDDLEWARE_CLASSES = ( 'my.apps.appmultisite.middleware.MultiSiteMiddleware', # Khai bao o tren cung!!! 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', ){/syntaxhighlighter}
Như vậy giờ đây chúng ta có thể áp dụng cho các project với nhiều subsite. ^^
Blog's topic:
- huyvq's blog
- Log in to post comments
- 2451 reads
Phản hồi