DJANGO
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.

Django Registration trong Python

Trong bài này, mình sẽ học cách tạo một form đăng ký Django cho phép người dùng đăng ký tài khoản. Hướng dẫn này sẽ tiếp nối từ phần cuối của hướng dẫn đăng nhập/đăng xuất Django, giúp bạn hoàn thiện hệ thống quản lý người dùng cho ứng dụng của mình.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Bắt đầu từ việc thiết lập form đăng ký, xử lý dữ liệu từ người dùng, cho đến việc tùy chỉnh và bảo mật thông tin, tất cả sẽ được trình bày một cách chi tiết và dễ hiểu. Hãy cùng tìm hiểu các bước để mang lại trải nghiệm người dùng tốt nhất cho web của bạn nhé.

Bạn có thể tải dự án form đăng ký Django bằng Python xuống tại đây.

Tạo Form đăng ký Django bằng Python

Bước đầu tiên, định nghĩa URL đăng ký trong urls.py của ứng dụng users:

from django.urls import path
from . import views
#Bài viết này được đăng tại freetuts.net

urlpatterns = [
    path('login/', views.sign_in, name='login'),
    path('logout/', views.sign_out, name='logout'),
    path('register/', views.sign_up, name='register'),
]

Tiếp theo, khai báo lớp RegisterForm trong forms.py của file users:

Bài viết này được đăng tại [free tuts .net]

from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm

class LoginForm(forms.Form):
    username = forms.CharField(max_length=65)
    password = forms.CharField(max_length=65, widget=forms.PasswordInput)
#Bài viết này được đăng tại freetuts.net

class RegisterForm(UserCreationForm):
    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2']

RegisterForm sử dụng mô hình User tích hợp sẵn và bao gồm bốn trường: tên người dùng, email, mật khẩu1 và mật khẩu2 mà người dùng cần điền vào để đăng ký.

Sau đó, định nghĩa hàm sign_up() trong views.py của ứng dụng users:

from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth import login, authenticate, logout
from .forms import LoginForm, RegisterForm
#Bài viết này được đăng tại freetuts.net

def sign_up(request):
    if request.method == 'GET':
        form = RegisterForm()
        return render(request, 'users/register.html', {'form': form})

Hàm sign_up() tạo đối tượng RegisterForm và render nó trong template register.html.

Tạo template register.html trong thư mục templates/users của ứng dụng users:

{% extends 'base.html' %}
#Bài viết này được đăng tại freetuts.net

{% block content %}
<form method="POST" novalidate>
    {% csrf_token %}
    <h2>Sign Up</h2>
    {{ form.as_p }}
    <input type="submit" value="Register" />
</form>
{% endblock content %}

register.html kế thừa từ template base.html của dự án. Nó render RegisterForm (form).

Lưu ý rằng thuộc tính novalidate loại bỏ xác thực HTML5. Sau khi hoàn thành dự án, bạn có thể loại bỏ thuộc tính này để bật xác thực HTML5.

Cuối cùng, mở URL đăng ký:

http://127.0.0.1:8000/register/

Bạn sẽ thấy form đăng ký như sau:

Tùy chỉnh Form đăng ký Django bằng Python

Form đăng ký có bốn trường với nhiều thông tin. Thông tin này đến từ mô hình User mặc định.

Nếu bạn muốn tùy chỉnh thông tin hiển thị trên form, bạn có thể sửa đổi template register.html như sau:

{% extends 'base.html' %}

{% block content %}
<form method="POST" novalidate>
    {% csrf_token %}
    <h2>Sign Up</h2>
    {% for field in form %}
    <p>
        {% if field.errors %}
        <ul class="errorlist">
            {% for error in field.errors %}
            <li>{{ error }}</li>
            {% endfor %}
        </ul>
        {% endif %}
        {{ field.label_tag }} {{ field }}
    </p>
#Bài viết này được đăng tại freetuts.net
    {% endfor %}
    <input type="submit" value="Register" />
</form>
{% endblock content %}

Template này lặp qua các trường của form và hiển thị từng trường một cách riêng biệt. Đối với mỗi trường, nó hiển thị danh sách lỗi nếu xác thực không thành công.

Form mới sẽ trông như sau:

Screenshot 202024 05 22 20170526 png

Nếu bạn điền thông tin và nhấn đăng ký, bạn sẽ nhận được lỗi vì mình chưa thêm mã xử lý yêu cầu HTTP POST.

Xử lý Logic đăng ký Django bằng Python

Để xử lý yêu cầu HTTP POST, bạn sửa đổi hàm sign_up() trong file views.py của ứng dụng users:

def sign_up(request):
    if request.method == 'GET':
        form = RegisterForm()
        return render(request, 'users/register.html', {'form': form})
#Bài viết này được đăng tại freetuts.net
    if request.method == 'POST':
        form = RegisterForm(request.POST)
        if form.is_valid():
            user = form.save(commit=False)
            user.username = user.username.lower()
            user.save()
            messages.success(request, 'You have signed up successfully.')
            login(request, user)
            return redirect('posts')
        else:
            return render(request, 'users/register.html', {'form': form})

Screenshot 202024 05 22 20170719 png

Cách hoạt động:

Đầu tiên, tạo một instance mới của RegisterForm:

form = RegisterForm(request.POST)

Nếu form hợp lệ, mình lưu form nhưng không lưu ngay vào cơ sở dữ liệu. Điều này được thực hiện bằng cách truyền đối số commit=False cho phương thức save() của đối tượng form.

Lý do là mình muốn chuyển tên người dùng thành chữ thường trước khi lưu vào cơ sở dữ liệu:

user.username = user.username.lower()
user.save()

Sau khi lưu người dùng, mình tạo thông báo flash, đăng nhập người dùng và chuyển hướng người dùng đến trang danh sách bài viết:

messages.success(request, 'You have signed up successfully.')
login(request, user)
return redirect('posts')

Nếu form không hợp lệ, mình sẽ render lại form với các giá trị đã nhập trước đó bằng cách truyền đối tượng form vào hàm render():

return render(request, 'users/register.html', {'form': form})

Ví dụ sau đây minh họa cách đăng ký một người dùng với tên người dùng là freetuts.net:

Screenshot 202024 05 22 20171021 png

Screenshot 202024 05 22 20171156 png

Thêm các liên kết

Đầu tiên, bao gồm liên kết đăng ký bằng cách sửa đổi template base.html. Cũng bao gồm các liên kết My Posts và New Post nếu người dùng đã đăng nhập:

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="{% static 'css/style.css' %}" />
    <script src="{% static 'js/app.js' %}" defer></script>
    <title>My Site</title>
</head>
<body>
    <header>
        {% if request.user.is_authenticated %}
            <a href="{% url 'posts' %}">My Posts</a>
            <a href="{% url 'post-create' %}">New Post</a>
            <span>Hi {{ request.user.username | title }}</span>
            <a href="{% url 'logout' %}">Logout</a>
        {% else %}
            <a href="{% url 'login' %}">Login</a>
            <a href="{% url 'register' %}">Register</a>
        {% endif %}
    </header>
    <main>
        {% if messages %}
#Bài viết này được đăng tại freetuts.net
        <div class="messages">
            {% for message in messages %}
            <div class="alert {% if message.tags %}alert-{{ message.tags }}"{% endif %}>
                {{ message }}
            </div>
            {% endfor %}
        </div>
        {% endif %}
        {% block content %} 
        {% endblock content %}
    </main>
</body>
</html>

djang register form header links png

Thứ hai, bao gồm liên kết đăng ký trong template login.html:

{% extends 'base.html' %}
#Bài viết này được đăng tại freetuts.net
{% block content %}
<form method="POST" novalidate>
    {% csrf_token %}
    <h2>Login</h2>
    {{ form.as_p }}
    <input type="submit" value="Login" />
    <p>Don't have an account? <a href="{% url 'register' %}">Register</a></p>
</form>
{% endblock content %}

djang register form login links png

Thứ ba, thêm liên kết đăng nhập vào trang register.html:

{% extends 'base.html' %}

{% block content %}
<form method="POST" novalidate>
    {% csrf_token %}
    <h2>Sign Up</h2>
    {% for field in form %}
    <p>
#Bài viết này được đăng tại freetuts.net
        {% if field.errors %}
        <ul class="errorlist">
            {% for error in field.errors %}
            <li>{{ error }}</li>
            {% endfor %}
        </ul>
        {% endif %}
        {{ field.label_tag }} {{ field }}
    </p>
    {% endfor %}
    <input type="submit" value="Register" />
    <p>Bạn đã có tài khoản? <a href="{% url 'login' %}">Login</a></p>
</form>
{% endblock content %}

Screenshot 202024 05 22 20180241 png

Ngăn người dùng chỉnh sửa/xóa bài viết của người khác

Thông thường, người dùng không nên có quyền chỉnh sửa hoặc xóa bài viết của người dùng khác. Tuy nhiên, người dùng có thể xem bài viết của người dùng khác.

Để triển khai chức năng này, mình cần kiểm tra xem tác giả của bài viết có giống với người dùng hiện tại đã đăng nhập hay không. Nếu có, mình sẽ hiển thị các form chỉnh sửa/xóa. Ngược lại, mình có thể chuyển hướng người dùng đến trang 404.

Ngoài ra, mình cần ẩn các liên kết chỉnh sửa và xóa của trang danh sách bài viết nếu bài viết không thuộc về người dùng.

Đầu tiên, sửa đổi views.py của ứng dụng blog:

from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .models import Post
from .forms import PostForm


@login_required
def delete_post(request, id):
    post = get_object_or_404(Post, pk=id)
    context = {'post': post}
#Bài viết này được đăng tại freetuts.net
    if request.method == 'GET':
        return render(request, 'blog/post_confirm_delete.html', context)
    elif request.method == 'POST':
        post.delete()
        messages.success(request,  'Bài viết đã được xóa thành công.')
        return redirect('posts')


@login_required
def edit_post(request, id):
    post = get_object_or_404(Post, id=id)

    if request.method == 'GET':
        context = {'form': PostForm(instance=post), 'id': id}
        return render(request, 'blog/post_form.html', context)
#Bài viết này được đăng tại freetuts.net
    elif request.method == 'POST':
        form = PostForm(request.POST, instance=post)
        if form.is_valid():
            form.save()
            messages.success(
                request, 'Bài viết đã được cập nhật thành công.')
            return redirect('posts')
        else:
            messages.error(request, 'Vui lòng chỉnh sửa lại các lỗi sau:')
            return render(request, 'blog/post_form.html', {'form': form})


@login_required
def create_post(request):
    if request.method == 'GET':
        context = {'form': PostForm()}
        return render(request, 'blog/post_form.html', context)
    elif request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            user = form.save(commit=False)
            user.author = request.user
            user.save()
            messages.success(request, 'Bài viết đã được tạo thành công.')
            return redirect('posts')
        else:
            messages.error(request, 'Vui lòng chỉnh sửa lại các lỗi sau:')
            return render(request, 'blog/post_form.html', {'form': form})

#Bài viết này được đăng tại freetuts.net
def home(request):
    posts = Post.objects.all()
    context = {'posts': posts}
    return render(request, 'blog/home.html', context)

Trong cả hai trường hợp xóa và cập nhật, mình lọc bài viết theo người dùng hiện tại trước khi truyền nó cho hàm get_object_or_404().

Nếu bạn đăng nhập dưới tên Jane và cố gắng chỉnh sửa một bài viết không thuộc về Jane, bạn sẽ nhận được lỗi 404. Ví dụ:

Screenshot 202024 05 22 20172308 png

Trang 404:

djang register form permissions 404 png

Thứ hai, sửa đổi template home.html để ẩn các liên kết chỉnh sửa và xóa.

{% extends 'base.html' %}

{% block content %}
<h1>My Posts</h1>
    {% for post in posts %}
        <h2>{{ post.title }}</h2>
        <small>Published on {{ post.published_at | date:"M d, Y" }} by {{ post.author | title }}</small>
        <p>{{ post.content }}</p>
#Bài viết này được đăng tại freetuts.net
        {% if request.user.is_authenticated and request.user == post.author %}
        <p>
            <a href="{% url 'post-edit' post.id %}">Edit</a>
            <a href="{% url 'post-delete' post.id %}">Delete</a>
        </p>
        {% endif %}
    {% endfor %}
{% endblock content %}

Loại bỏ tác giả khỏi form tạo bài viết

Đầu tiên, loại bỏ trường tác giả khỏi các trường của lớp PostForm:

from django.forms import ModelForm
from .models import Post

class PostForm(ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'content']

Form tạo bài viết sẽ trông như thế này:

Screenshot 202024 05 22 20172323 png

Thứ hai, sửa đổi hàm create_post() trong views.py của ứng dụng blog để cập nhật tác giả của bài viết thành người dùng hiện tại đã đăng nhập:

@login_required
def create_post(request):
#Bài viết này được đăng tại freetuts.net
    if request.method == 'GET':
        context = {'form': PostForm()}
        return render(request, 'blog/post_form.html', context)
    elif request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            user = form.save(commit=False)
            user.author = request.user
            user.save()
            messages.success(request, 'The post has been created successfully.')
            return redirect('posts')
        else:
            messages.error(request, 'Please correct the following errors:')
            return render(request, 'blog/post_form.html', {'form': form})

Bạn có thể tải dự án form đăng ký Django bằng Python xuống tại đây.

Kết bài

Qua hướng dẫn này, bạn đã học được cách tạo một form đăng ký Django giúp người dùng có thể đăng ký tài khoản một cách dễ dàng và bảo mật. Từ việc thiết lập URL và form đăng ký, xử lý yêu cầu HTTP, đến việc tùy chỉnh giao diện và bảo vệ dữ liệu người dùng, bạn đã nắm bắt được các bước cơ bản và quan trọng để xây dựng một hệ thống quản lý người dùng hoàn chỉnh. Việc tích hợp chức năng đăng ký này không chỉ nâng cao trải nghiệm người dùng mà còn giúp bạn quản lý người dùng hiệu quả hơn. Hãy tiếp tục tìm hiểu những công cụ mà Django cung cấp để phát triển các ứng dụng web chuyên nghiệp và đáng tin cậy.

Danh sách file tải về

Tên file tải về Pass giải nén
Django Registration trong Python Không có

Cùng chuyên mục:

Tìm hiểu Event loop trong Python

Tìm hiểu Event loop trong Python

Cách sử dụng ProcessPoolExecutor trong Python

Cách sử dụng ProcessPoolExecutor trong Python

Sử dụng đa xử lý trong Python

Sử dụng đa xử lý trong Python

Cách sử dụng Thread-safe Queue trong Python

Cách sử dụng Thread-safe Queue trong Python

Sử dụng Semaphore trong Python

Sử dụng Semaphore trong Python

Cách dừng Luồng trong Python

Cách dừng Luồng trong Python

Cách sử dụng Semaphore trong Python

Cách sử dụng Semaphore trong Python

Đối tượng Threading Event trong Python

Đối tượng Threading Event trong Python

Tìm hiểu về điều kiện race của threading Lock trong Python

Tìm hiểu về điều kiện race của threading Lock trong Python

Sử dụng lớp ThreadPoolExecutor trong Python

Sử dụng lớp ThreadPoolExecutor trong Python

Các luồng Daemon trong Python

Các luồng Daemon trong Python

Tìm hiểu về Multithreading trong Python

Tìm hiểu về Multithreading trong Python

Cách trả về giá trị từ một Thread trong Python

Cách trả về giá trị từ một Thread trong Python

Cách mở rộng Class Thread trong Python

Cách mở rộng Class Thread trong Python

Cách sử dụng module threading trong Python

Cách sử dụng module threading trong Python

Sự khác biệt giữa các Processes and Threads

Sự khác biệt giữa các Processes and Threads

Tài liệu tham khảo nhanh về Regex trong Python

Tài liệu tham khảo nhanh về Regex trong Python

Hàm Flags của Regex trong Python

Hàm Flags của Regex trong Python

Hàm split() của Regex trong Python

Hàm split() của Regex trong Python

Hàm finditer() của Regex trong Python

Hàm finditer() của Regex trong Python

Top