Django – Sessions

5/5 - (8 votes)

Đô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 trong loại này không được đảm bảo vì nếu bộ nhớ cache đầy thì dữ liệu session sẽ bị xóa, nhưng loại này truy xuất dữ liệu cũng như ghi dữ liệu rất nhanh.
  • django.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_ENGINEdjango.contrib.sessions.backends.fileSESSION_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_ENGINEdjango.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()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 usernameadminpassword123. 

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.

Capture

Đăng nhập với usernameadminpassword123 để được chuyển đến trang chào mừng.

Capture1

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.

Capture2

5 1 vote
Article Rating
Subscribe
Thông báo cho tôi qua email khi
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Inline Feedbacks
View all comments
Đức PhạmTrung
Đức PhạmTrung
8 năm trước

Bài viết ví dụ rất rõ ràng và bổ ích ạ. Cảm ơn anh.