Đôi khi chúng ta muốn lưu lại một số thông tin trong quá trình duyệt web của user để sử dụng lại sau này, session cho phép chúng ta lưu trữ lại một số thông tin trên từng user, session có nhiều loại, có loại lưu dữ liệu trên server, có loại lưu trên client… Trong phần này chúng ta sẽ tìm hiểu về hệ thống session của Django.
Kích hoạt session
Chúng ta kích hoạt session bằng cách khai báo django.contrib.middle.SessionMiddleware
trong biến MIDDLEWARE_CLASSES
trong file settings.py:
MIDDLEWARE_CLASSES = [ #..., 'django.contrib.sessions.middleware.SessionMiddleware', #... ]
Mặc định thì session đã được kích hoạt sẵn khi tạo project nên chúng ta cũng không cần phải chỉnh sửa gì trong này.
Cấu hình session
Dữ liệu trong session có thể được lưu trong cơ sở dữ liệu, file hoặc trong cache, mặc định thì Django lưu trong CSDL.
Lưu session trong cơ sở dữ liệu
Để cấu hình session lưu trong cơ sở dữ liệu thì chúng ta khai báo django.contrib.sessions
trong biến INSTALLED_APPS:
INSTALLED_APPS = [ #... 'django.contrib.sessions', #... ]
Sau khi thiết lập thì chúng ta phải chạy lệnh manage.py migrate
để Django tạo bảng tương ứng trong CSDL.
Lưu session trong cache
Bạn chỉ nên dùng loại session này nếu bạn thiết lập kiểu cache của server là memcached. Để lưu session trong cache thì chúng ta thiết lập biến
SESSION_ENGINE
trong file settings.py
là:
django.contrib.sessions.backends.cache:
session lưu trongdjango.contrib.sessions.backends.cached_db:
loại này thì vừa lưu dữ liệu session trong cache vừa lưu vào CSDL luôn, nếu session trong cache bị xóa thì Django sẽ tìm session trong CSDL nên dữ liệu được đảm bảo hơn loại trên nhưng cũng vì thế và tốc độ chậm hơn.
Trong thực tế thì chúng ta sẽ dùng loại thứ 2 vì dữ liệu session thường cũng không lớn nên việc đọc ghi sẽ không tốn thời gian mấy. Cũng chính vì loại thứ 2 lưu session trong cơ sở dữ liệu nên chúng ta cũng phải thiết lập luôn cả phần Lưu session trong cơ sở dữ liệu ở trên.
Lưu session trong file
Để lưu session trong file thì chúng ta khai báo SESSION_ENGINE
là django.contrib.sessions.backends.file
và SESSION_FILE_PATH
là đường dẫn đến tên file dùng để lưu session, đường dẫn phải là đường dẫn tuyệt đối và server phải có quyền đọc/ghi file trên đĩa cứng.
Lưu session trong cookie
Chúng ta khai báo SESSION_ENGINE
là django.contrib.sessions.backends.signed_cookies.
Bạn để ý là trong file settings.py
có một biến tên là SECRET_KEY
có giá trị là một chuỗi được Django tạo ra ngẫu nhiên, biến này sẽ được dùng để mã hóa dữ liệu trong sessions, chúng ta sẽ tìm hiểu về biến này sau.
Truy xuất session trong view
Tham số request trong hàm view sẽ chứa một thuộc tính có tên là session
khi SessionMiddleware
được kích thoạt, đây là một đối tượng dictionary. Chúng ta có thể đọc/ghi thuộc tính này ở bất kỳ đâu trong hàm view.
Dưới đây là một số thao tác với session:
Lấy giá trị theo khóa:
>>> color = request.session['color'] >>> color1 = request.session.get('color', 'red')
Tham số 'red'
là tham số trả về mặc định, tức là nếu không tìm thấy khóa 'color'
trong session thì trả về giá trị 'red'.
Thiết lập khóa:
>>> request.session['color'] = 'blue'
Xóa khóa ra khỏi session,
nếu không tìm thấy khóa thì báo lỗi KeyError:
>>> del request.session['color']
Kiểm tra xem khóa có tồn tại trong session:
>>> 'color' in request.session
Xóa toàn bộ dữ liệu session:
>>> request.session.flush()
Thiết lập thời gian tồn tại cho session, tham số nhận vào là số giây, nếu để 0 thì tồn tại cho đến khi user tắt trình duyệt.
>>> request.session.set_expiry(300)
Lấy thời gian còn lại của sessiontheo giây.
>>> request.session.get_expiry_age()
Ví dụ
Chúng ta sẽ xây dựng một hệ thống login (đăng nhập) có hỗ trợ session đơn giản. Mặc định project của mình có tên cũng như thư mục là mysite.
Chúng ta tạo app có tên là login
(
nhớ khai báo trong biến INSTALLED_APP)
:
C:\Project\mysite>python manage.py startapp login
Bên trong app chúng ta tạo lớp form với tên LoginForm:
from django import forms class LoginForm(forms.Form): username = forms.CharField(max_length = 100) password = forms.CharField(widget = forms.PasswordInput())
Tiếp theo chúng ta tạo 2 trang template, một trang dùng để hiển thị form đăng nhập, một trang template để hiển thị thông báo đăng nhập thành công.
<form action="{% url 'login.views.loginView' %}" method="POST"> {% csrf_token %} <table> <tr> <td>Username:</td> <td><input type="text" name="username" /></td> </tr> <tr> <td>Password:</td> <td><input type="password" name="password" /></td> </tr> <tr> <td></td> <td><input type="submit" value="Login"/></td> </tr> </table> </form>
File login.html
dùng để hiển thị form đăng nhập. Tại đây thuộc tính action
trong thẻ form
trỏ đến hàm loginView
mà chúng ta sẽ viết ở dưới.
Hello, <strong>{{username}}</strong>
File loggedin.html
hiển thị thông báo đăng nhập thành công.
Tiếp theo chúng ta viết các hàm view.
from django.shortcuts import render from django.http import HttpResponse # Create your views here. from login.forms import LoginForm def loginView(request): username = "Wrong username or password" if request.method == "POST": MyLoginForm = LoginForm(request.POST) if MyLoginForm.is_valid(): if MyLoginForm.cleaned_data['username'] == 'admin': if MyLoginForm.cleaned_data['password'] == '123': username = MyLoginForm.cleaned_data['username'] request.session['username'] = username request.session.set_expiry(15); else: MyLoginForm = LoginForm() return render(request, 'loggedin.html', {'username':username}) def formView(request): if request.session.has_key('username'): username = request.session['username'] return render(request, 'loggedin.html', {'username':username}) else: return render(request, 'login.html', {}) def logoutView(request): try: del request.session['username'] except: pass return HttpResponse("Good bye!")
Chúng ta viết 3 hàm view là loginView(), formView()
và logoutView().
if MyLoginForm.cleaned_data['username'] == 'admin': if MyLoginForm.cleaned_data['password'] == '123':
Hàm loginView()
sẽ kiểm tra dữ liệu được gửi lên. Ở đây chúng ta chỉ kiểm tra đơn giản với username
là admin
và password
là 123.
username = MyLoginForm.cleaned_data['username'] request.session['username'] = username request.session.set_expiry(15);
Nếu dữ liệu phù hợp thì chúng ta thiết lập khóa username
và thời gian hiệu lực là 15 giây trong thuộc tính session.
if request.session.has_key('username'): username = request.session['username'] return render(request, 'loggedin.html', {'username':username}) else: return render(request, 'login.html', {})
Hàm formView()
sẽ kiểm tra xem session có chứa dữ liệu hay không bằng phương thức has_key(),
nếu chưa có thì tạo form đăng nhập với template login.html.
Còn nếu có rồi thì hiển thị câu chào mừng trong template loggedin.html.
try: del request.session['username']
Hàm logoutView()
có nhiệm vụ xóa khóa username
trong session nếu có.
Cuối cùng là tạo URL:
from django.conf.urls import url, include, patterns urlpatterns = patterns('login.views', url(r'^login/', 'loginView'), url(r'^greeting/', 'formView'), url(r'^logout/', 'logoutView') )
Khác với các bài trước là chúng ta tạo URL cho riêng từng app, ở đây chúng ta cho trỏ URL thẳng đến các hàm view trong app luôn. Lớp patterns
nhận vào tham số đầu tiên là đường dẫn đến module chứa các hàm view, các tham số tiếp theo là các đối tượng url.
Bây giờ chúng ta có thể chạy server và trỏ đến URL localhost:8000/greeting để đăng nhập.
Đăng nhập với username là admin và password là 123 để được chuyển đến trang chào mừng.
Nếu chưa hết 15 giây mà chúng ta lại trỏ đến localhost:8000/greeting thì Django sẽ hiện ra trang “Hello,…” luôn chứ không hiện ra form đăng nhập nữa.
Ngoài ra chúng ta có thể trỏ đến localhost:8000/logout để xóa session là có thể đăng nhập lại.