Khung nghỉ Django từ cơ bản đến nâng cao
By datnq, at: 17:03 Ngày 19 tháng 12 năm 2023
Thời gian đọc ước tính: __READING_TIME__ minutes


Chúng ta sẽ bắt đầu với những kiến thức cơ bản về RESTful APIs, làm quen với serializers, authentication, và cuối cùng là đi sâu vào những chủ đề nâng cao đầy thử thách. Với những hiểu biết thực tiễn và các ví dụ cụ thể, bài viết này hứa hẹn sẽ mang đến cho bạn một trải nghiệm học tập phong phú, giúp bạn thành thạo Django Rest Framework từng bước một. Hãy bắt đầu cuộc phiêu lưu của bạn từ người mới bắt đầu đến chuyên gia ngay hôm nay!
1. Cách tạo một api cơ bản, luồng chạy
Các thành phần chính của một api cơ bản trong drf bao gồm 2 phần: serializer và view. Sau khi import thư viện và thiết lập mọi thứ thành công, giả sử bạn muốn tạo một api cơ bản với phương thức GET để truy xuất tất cả dữ liệu về sách. Với serializers:
from app.models import Book
from rest_framework import serializers
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['name', 'author', 'rate']
Serializer của DRF hỗ trợ việc serialize và deserialize từ mã Python sang JSON. Ở đây UserSerializer sẽ trả về kết quả API chứa các trường name, author, rate
View trong DRF là cách để truy cập API thông qua các thuộc tính.
from app.models import Book
from rest_framework import permissions, viewsets
from app.serializers import BookSerializer
class UserViewSet(viewsets.ModelViewSet):
serializer_class = BookSerializer
permission_classes = [permissions.IsAuthenticated]
Với một view đơn giản, DRF đã tạo ra một API trả về dữ liệu sách theo BookSerializer ở trên. Thuộc tính permission_classes được khai báo để yêu cầu xác thực người dùng nếu muốn API thực thi.
2. Tùy chỉnh trường, validate trong serializer
Ngoài việc sử dụng các trường có sẵn trong model, người dùng cũng có thể trả về kết quả API dựa trên các trường tự tạo.
class BookSerializer(serializers.ModelSerializer):
date_publish = serializers.SerializerMethodField()
class Meta:
model = Message
fields = ['name', 'author', 'rate', 'date_publish']
def get_date_publish(self, obj):
"""
logic code for result of date publish
"""
Với một view đơn giản, DRF đã tạo ra một API trả về dữ liệu sách theo BookSerializer ở trên. Thuộc tính allow_classes khai báo mục tiêu yêu cầu mục tiêu được xác thực bởi người dùng nếu muốn API thực thi.
3. Tùy chỉnh trường, validation trong serializer
Ngoài việc sử dụng các trường có sẵn trong model, người dùng cũng có thể trả về kết quả API dựa trên các trường được tự động tạo.
class BookSerializer(serializers.ModelSerializer):
date_publish = serializers.SerializerMethodField()
class Meta:
model = Message
fields = ['name', 'author', 'rate', 'date_publish']
def get_date_publish(self, obj):
"""
logic code for result of date publish
"""
Đối với mỗi cuốn sách dữ liệu, date_publish có cùng giá trị với bất kỳ giá trị phụ thuộc nào được trả về bởi hàm get_date_publish.
Bên cạnh đó, chúng ta cũng cần validate xem tỉ lệ có giá trị hợp lý hay không. DRF cũng hỗ trợ điều này. Lấy ví dụ đơn giản, tính điểm của một cuốn sách yêu cầu giá trị lớn hơn 0 và nhỏ hơn 5. Cần thêm một hàm để kiểm tra giá trị trả về tỉ lệ cho class BookSerializer.
def validate_rate(self, value):
if value < 0 or value > 5:
raise serializers.ValidationError("Error")
return value
DRF hỗ trợ mạnh mẽ serializers, mang lại cho người dùng sự linh hoạt trong việc tạo serializers theo ý muốn.
4. So sánh các Views
Khi nói đến views và views người mới bắt đầu sẽ có khá nhiều sự tự do trong công việc của mình, để lựa chọn loại API phù hợp để sử dụng. Dưới đây là bảng so sánh được vẽ ra để dễ quan sát hơn.
Loại View | Trường hợp sử dụng |
function view | Đây là loại view cơ bản, dễ tạo và dễ hiểu. Tuy nhiên, do không tuân theo bất kỳ quy tắc nào nên việc bảo trì code về sau gặp khó khăn, hạn chế sử dụng. |
class APIView | Có cơ chế tương tự như function view, điểm cải tiến là class hỗ trợ nhiều phương thức thuộc tính để phục vụ request, dễ bảo trì hơn, hỗ trợ một số chức năng cụ thể hơn như .get(), và .post(). Tuy nhiên vẫn còn nhiều hạn chế |
class GenericAPIView | Một cải tiến nổi bật của drf, GenericAPIView, mình cảm thấy là một class rất tốt để sử dụng để tạo API. Điểm nhấn phải kể đến khi sử dụng GenericAPIView đó là cho phép sử dụng query set, cho phép mapping đến một serializer_class riêng,... và đặc biệt là sử dụng mixins. Điều này gợi nhớ đến generic class-based view của Django. Ngoài ra, chúng ta có thể đơn giản hóa API với các concrete view classes (ví dụ, nếu chỉ có 1 API get cho model, thay vì dùng GenericAPIView, chúng ta có thể dùng ListAPIView) |
class ViewSet | Tương tự như class APIView, tuy nhiên thay vì các hàm chung .get(), .post(), ViewSet chỉ định hai phương thức: .list() và .create(). Điểm mạnh của viewsets là tự động khai báo URL theo đăng ký thay vì tạo URL thủ công như các views ở trên |
function GenericViewSet | Tương tự như GenericAPIView, hỗ trợ tự động sinh URL theo đăng ký |
class ModelViewSet | Tương tự như GenericViewSet, hỗ trợ tự động sinh URL, với thêm hỗ trợ .list(), .retrieve(), .create(), .update(), .partial_update(), và .destroy() |
5. Các hành động tùy chỉnh
Như các bạn đã biết, viewset hỗ trợ tự động sinh urls:
from app.models import Book
from app.serializers import BookSerializer
from rest_framework import viewsets
class BookViewSet(viewsets.ViewSet):
def list(self, request):
queryset = Book.objects.all()
serializer = BookSerializer(queryset, many=True)
return Response(serializer.data)
Trên đây là một ví dụ đơn giản về ViewSet tạo API để truy xuất tất cả dữ liệu sách. Để khai báo endpoint cho API này, chỉ cần thêm đoạn sau vào urls.py:
router.register(r'books', BookViewSet, basename='book')
Đoạn code trên giúp tự động khai báo các API trong class BookViewSet. Trong trường hợp muốn tạo một API cụ thể theo ý muốn, DRF có extra_action để hỗ trợ điều này:
@action(detail=True, methods=["get"], name="Example")
def example(self, request, pk=None):
"""Logic code here"""
...
Giờ đây người dùng đã có một API /example của books với phương thức GET.
6. Sử dụng filter và custom permission, authentication
Vậy là mọi người hiện đã hiểu hơn về framework, một số cách đăng ký API, cách chọn view phù hợp và thiết kế serializer. Đối với mỗi API, luôn có bộ lọc và xác thực người dùng được thiết lập. Kết thúc bài viết, mình xin được để lại một số cách đơn giản để tạo filter, permission và authentication tùy thuộc vào yêu cầu.
6.1. Với filter:
Bạn có thể sử dụng một số filter backend có sẵn như:
- DjangoFilterBackEnd
- SearchFilter
- OrderingFilter
Ngoài ra, bạn có thể tìm hiểu về thư viện thứ ba 'django_filter' trong trường hợp muốn tạo filter nâng cao theo yêu cầu.(https://django-filter.readthedocs.io/en/stable/guide/install.html)
6.2. Với permission và authentication:
Ghi đè các hàm BasePermission và BaseAuthentication để sử dụng theo ý muốn.
Ví dụ:
from rest_framework.permissions import BasePermission
class ExamplePermission(BasePermission):
def has_permission(self, request, view):
"""
write logic here, return True if successful, otherwise return False
"""
Kết luận
Hướng dẫn này đã hướng dẫn bạn những kiến thức cơ bản về Django Rest Framework, từ việc thiết lập các API cơ bản đến việc tùy chỉnh serializers và hiểu các loại view khác nhau. Bằng cách làm theo các bước và ví dụ này, hiện tại bạn nên có một nền tảng vững chắc trong DRF, sẵn sàng để giải quyết các chủ đề nâng cao hơn.
Hãy đón chờ Phần 2, nơi chúng ta sẽ đi sâu hơn vào các tính năng DRF nâng cao, bao gồm các serializers phức tạp hơn, cơ chế xác thực tùy chỉnh và các kỹ thuật tối ưu hóa hiệu suất. Hãy tiếp tục học tập và khám phá!