Advanced Django REST framework
Bài đăng này đã không được cập nhật trong 7 năm
Giới thiệu 1 số tính năng của django REST framework
Ở bài trước mình đã giới thiệu cho các bạn cách tạo ra một REST API căn bản từ 1 project django.
Link tại đây https://viblo.asia/p/gioi-thieu-django-rest-framework-Eb85oJb2l2G
Bài này mình sẽ giới thiệu tiếp 1 số tính năng thêm của django REST framework.
Gồm có:
- Customize serializer
- Overide API's functions
Customize serializer
Customize field
Ở phần trước trong serializer của Post Model mình để fields = '__all__'
thực ra chỉ để cho nhanh. trong thực tế mình sẽ ko dùng hết tất cả các field của model:
# serializer.py
# Định nghĩa model cần serialize và các trường:
class PostListSerializer(serializers.ModelSerializer):
class Meta:
model = Post
# ko dùng đến updated và created
fields = ('title', 'content', 'draft', 'read_time', )
# định nghĩa trường chỉ cho phép đọc
read_only_fields = ('draft', 'read_time')
Ở đây read_only_fields
chỉ những trường chỉ cho phép đọc. Tức là chỉ dùng phương thức GET
. Còn cụ thể dùng như thế nào, trong trường hợp nào thì mình sẽ nói ở bên dưới phần CustomAPI
Trong thực tế ta sẽ dùng một số custom field. Trong trường hợp này ta sẽ sử dùng property của Model hoặc nếu chỉ dùng trường đó cho riêng API thì ta dùng serializers.SerializerMethodField
. giả sử trong trường hợp này ta format lại trường created
.
# serializer.py
class PostListSerializer(serializers.ModelSerializer):
# khai báo trường custom
created_formated = serializers.SerializerMethodField(read_only=True)
# hàm này để get dữ liệu cho trường created_formated
def get_created_formated(post)
# return dd-mm-yyyy format
return post.created.strftime("%d-%m-%Y")
class Meta:
model = Post
fields = ('title', 'content', 'draft', 'read_time', 'created_formated')
read_only_fields = ('draft', 'read_time')
Trong trường hợp có quá nhiều trường mà ta chỉ bỏ 1 hoặc 2 trường. Thì việc liệt kê tất cả các trường ra là một cực hình.
ta có thể dùng exclude
thay cho fields
, để chỉ ra những trường nào ko dùng trong model
class PostListSerializer(serializers.ModelSerializer):
class Meta:
model = Post
# ko dùng đến updated và created
exclude = ('updated', 'created',)
# định nghĩa trường chỉ cho phép đọc
read_only_fields = ('draft', 'read_time')
Validate Field
Việc validate một trường có thể được viết trong model nhưng đối với một trường custom thì ta phải validate ở đây. hoặc trong trường hợp ta muốn chỉ validate cho riêng API này thôi. Vì viết trong model sẽ validate ở tất cả những nơi dùng model đó.
ví dụ ta muốn validate trường title: đơn giản ta khai báo một hàm có tên validate_title
. cú pháp chung sẽ là validate_+têntrường
:
class PostListSerializer(serializers.ModelSerializer):
def validate_title(self, value):
"""
Kiểm tra trong tiêu đề có từ django hay không. không có sẽ báo lỗi.
"""
if 'django' not in value.lower():
raise serializers.ValidationError("Blog post is not about Django")
return value
Validate Object
Trong trường hợp ta muốn validate trên nhiều field cùng lúc. ta có thể dùng hàm validate trong serializer
class PostListSerializer(serializers.ModelSerializer):
start = serializers.DateTimeField()
finish = serializers.DateTimeField()
def validate(self, data):
"""
Kiểm tra nếu start lớn hơn stop.
"""
if data['start'] > data['finish']:
raise serializers.ValidationError("finish must occur after start")
return data
NOTE: ta có thể validate ở tầng model hoặc tầng serializer. Trong mọi trường hợp thì việc validate của Model sẽ trả về lỗi trước. sau đó mới đến phần validate ở Serializer. REST API của ta sẽ ko trả về validate của tất cả các fields cùng một lúc. Sẽ khó khăn cho việc frontend hiển thị lỗi. Nên mình khuyến nghị chỉ validate ở một nơi thôi.
Dùng Validator
Trong nhiều trường hợp ta có vể viết một hàm validate để có thể sử dụng cho nhiều field ở nhiều nơi khác nhau. Cú pháp như sau:
def multiple_of_ten(value):
if value % 10 != 0:
raise serializers.ValidationError('Not a multiple of ten')
class GameRecord(serializers.Serializer):
# NOTE: là một list các validator => có thể là nhiều loại validate.
score = IntegerField(validators=[multiple_of_ten])
Serialier lồng nhau.
class UserSerializer(serializers.Serializer):
email = serializers.EmailField()
username = serializers.CharField(max_length=100)
class CommentSerializer(serializers.Serializer):
user = UserSerializer()
# user = UserSerializer(required=False) => trong trường hợp người dùng ẩn danh hoặc ko muốn đăng ký.
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
Một số thư viện bên thứ 3 cho serializer
- django-rest-marshmallow
- django-rest-framework-mongoengine
- django-rest-framework-gis
- django-rest-framework-hstore
- dynamic-rest
- drf-dynamic-fields
- django-rest-framework-serializer-extensions
- html-json-forms
- DRF-Base64
- drf-writable-nested
Phần này cũng đã khá dài. còn phần Custom API mình sẽ để dành cho bài tiếp theo. Bài viết chắc có nhiều thiếu xót. mọi người cứ thoải mái blame nhé.
From Cherry with Love.
Thanks for watching ~!
All rights reserved