Mối quan hệ giữa tham số attrs và validated_data trong serializers của Django REST Framework

# file serializers.py
from rest_framework import serializers
class DangKySerializer(serializers.ModelSerializer):
    mat_khau_xac_nhan = serializers.CharField(label='Xác nhận mật khẩu', help_text='Vui lòng nhập lại mật khẩu',
                                            write_only=True, min_length=6, max_length=20,
                                            error_messages={
                                                'min_length': 'Mật khẩu chỉ được phép 6-20 ký tự',
                                                'max_length': 'Mật khẩu chỉ được phép 6-20 ký tự',
                                            })

    class Meta:
        model = NguoiDung
        # fields quyết định các trường nào tham gia vào quá trình tuần tự hóa và tuần tự hóa ngược,
        # quyết định các tham số đầu ra cho trình duyệt và các tham số đầu vào vào cơ sở dữ liệu.
        fields = ['id', 'ten_dang_nhap', 'mat_khau', 'mat_khau_xac_nhan', 'email', 'so_dien_thoai']
        # sửa đổi tham số của trường mô hình
        extra_kwargs = {
            'ten_dang_nhap': {
                'min_length': 6,
                'max_length': 20,
                'error_messages': {
                    'min_length': 'Tên đăng nhập chỉ được phép 6-20 ký tự',
                    'max_length': 'Tên đăng nhập chỉ được phép 6-20 ký tự',
                }
            },
            'so_dien_thoai': {
                'required': True,
                'error_messages': {
                    'required': 'Phải cung cấp số điện thoại'
                }
            },
            'mat_khau': {
                'min_length': 6,
                'max_length': 20,
                'write_only': True,
                'error_messages': {
                    'min_length': 'Mật khẩu chỉ được phép 6-20 ký tự',
                    'max_length': 'Mật khẩu chỉ được phép 6-20 ký tự',
                }
            },
            'email': {
                'required': True,
                'validators': [UniqueValidator(queryset=model.objects.all(), message='Email này đã được đăng ký')]
            }
        }

    def validate(self, thuoc_tinh):
        # hàm validate nhận thuoc_tinh là các tham số được gửi từ phía client.
        mat_khau = thuoc_tinh.get('mat_khau')
        mat_khau_xac_nhan = thuoc_tinh.pop('mat_khau_xac_nhan')
        if mat_khau_xac_nhan != mat_khau:
            raise serializers.ValidationError('Mật khẩu và mật khẩu xác nhận không khớp')

        return thuoc_tinh

    def create(self, du_lieu_da_xac_thuc):
        """
        Tạo bản ghi mới, du_lieu_da_xac_thuc là dữ liệu đã được phương thức validate xác thực và xử lý,
        là đường truyền dữ liệu quan trọng trong quy trình thực thi của serializer DRF [xác thực - xử lý - tạo]
        
        """
        # Cách 1:
        # mat_khau = du_lieu_da_xac_thuc.get('mat_khau')
        # mat_khau = make_password(mat_khau)
        # du_lieu_da_xac_thuc['mat_khau'] = mat_khau
        # return super().create(du_lieu_da_xac_thuc)

        # Cách 2:
        # instance: NguoiDung = super().create(du_lieu_da_xac_thuc)
        # instance.set_password(instance.mat_khau)
        # instance.save()
        # return instance

        # Cách 3:
        return NguoiDung.objects.create_user(**du_lieu_da_xac_thuc)

Mối quan hệ giữa thuoc_tinh trong hàm validate(self, thuoc_tinh)du_lieu_da_xac_thuc trong hàm create(self, du_lieu_da_xac_thuc) — kết luận cốt lõi là: du_lieu_da_xac_thucthuoc_tinh đã được phương thức validate xác thực và xử lý, là chuỗi truyền dữ liệu quan trọng trong quy trình thực thi của serializer DRF "xác thực → xử lý → tạo". Dưới đây tôi sẽ phân tích quy trình này, kết hợp với mã nguồn của bạn để giải thích chi tiết mối quan hệ và cách sử dụng của cả hai.

I. Các khái niệm cốt lõi

II. Quy trình thực thi của serializer DRF (quan trọng) Đây là nền tảng để hiểu mối quan hệ giữa hai tham số, quy trình đăng ký serializer của bạn như sau:

  1. Tiếp nhận dữ liệu đầu vào: Client gửi request với dữ liệu JSON
  2. Chuyển đổi thành từ điển: DRF chuyển JSON thành từ điển Python
  3. Gọi validate với tham số attrs: Dữ liệu từ điển được truyền vào hàm validate dưới dạng tham số attrs
  4. Xác thực dữ liệu: Trong hàm validate, bạn thực hiện các kiểm tra tùy chỉnh
  5. Trả về dữ liệu đã xác thực: Hàm validate trả về dữ liệu đã xử lý
  6. Gán cho validated_data: Dữ liệu trả về từ validate được gán cho validated_data
  7. Gọi create với validated_data: Dữ liệu đã xác thực được truyền vào hàm create
  8. Tạo đối tượng: Hàm tạo bản ghi trong cơ sở dữ liệu bằng dữ liệu đã xác thực

III. Sử dụng cụ thể trong mã nguồn của bạn

1. Sử dụng attrs (trong phương thức validate):

def validate(self, thuoc_tinh):
    # 1. Lấy các trường cần xác thực từ thuoc_tinh
    mat_khau = thuoc_tinh.get('mat_khau')
    mat_khau_xac_nhan = thuoc_tinh.pop('mat_khau_xac_nhan')  # Lấy và xóa trường không thuộc mô hình
    
    # 2. Xác thực chéo các trường (kịch bản chính)
    if mat_khau_xac_nhan != mat_khau:
        raise serializers.ValidationError('Mật khẩu và mật khẩu xác nhận không khớp')
    
    # 3. Trả về thuoc_tinh đã xử lý (trở thành validated_data sau này)
    return thuoc_tinh

Kịch bản điển hình: Xác thực chéo các trường (mật khẩu + xác nhận mật khẩu), loại bỏ các trường không thuộc mô hình, định dạng dữ liệu (ví dụ: loại bỏ khoảng trắng trong số điện thoại).

2. Sử dụng validated_data (trong phương thức create):

def create(self, du_lieu_da_xac_thuc):
    # Sử dụng trực tiếp dữ liệu đã xác thực sạch để tạo người dùng
    return NguoiDung.objects.create_user(**du_lieu_da_xac_thuc)

Kịch bản điển hình: Giải nén truyền vào phương thức tạo của mô hình (create_user/create), gán giá trị cho các trường của mô hình, các logic bổ sung khi lưu vào cơ sở dữ liệu (ví dụ: mã hóa mật khẩu).

IV. Những điểm dễ mắc lỗi phổ biến

1. Không thực hiện xác thực trong phương thức create:

Logic xác thực phải được đặt trong phương thức validate, create chỉ chịu trách nhiệm tạo bản ghi — nếu phát hiện lỗi dữ liệu trong create, ngoại lệ được ném ra sẽ không được DRF xử lý chuẩn hóa, client sẽ nhận được lỗi 500 không thân thiện.

2. Phương thức validate phải trả về từ điển:

Nếu bạn sửa đổi thuoc_tinh trong validate, hãy đảm bảo luôn return thuoc_tinh (hoặc từ điển đã xử lý), nếu không du_lieu_da_xac_thuc sẽ rỗng, dẫn đến thất bại khi tạo bản ghi.

3. Các trường không thuộc mô hình phải được loại bỏ trong validate:

Ví dụ mat_khau_xac_nhan là trường tùy chỉnh (mô hình NguoiDung không có), nếu không được loại bỏ bằng thuoc_tinh.pop(), việc gọi create_user sau này sẽ báo lỗi "tham số không xác định".

Tóm tắt

Mối quan hệ: du_lieu_da_xac_thucthuoc_tinh đã được phương thức validate xác thực và xử lý, là chuỗi truyền dữ liệu cốt lõi từ "xác thực" đến "tạo" trong serializer DRF;

Cách sử dụng attrs: Trong validate thực hiện xác thực chéo các trường, loại bỏ các trường không thuộc mô hình, tiền xử lý dữ liệu;

Cách sử dụng validated_data: Trong create sử dụng trực tiếp để tạo bản ghi mô hình, không cần xác thực thêm, đảm bảo dữ liệu an toàn khi lưu vào cơ sở dữ liệu.

Cách đơn giản để ghi nhớ: thuoc_tinh là "nguyên liệu thô", du_lieu_da_xac_thuc là "sản phẩm hoàn chỉnh", validate là "nhà máy xử lý", create là "giai đoạn sử dụng sản phẩm".

Thẻ: Django REST Framework serializers validate create attrs

Đăng vào ngày 3 tháng 8 lúc 08:47