Series Django (P3): Thao tác với post app qua Django rest framework

Chào mọi người, lâu lắm mới quay lại với series Django này. Ở phần trước mình đã thử bước đầu thao tác với Django rest-framework với ListAPIView. Ở phần này mình sẽ đi với các thao tác còn lại trong CRUD.

1. Retrieve View Detail

Mình sẽ thêm PostDetailAPIView trong posts/api/views.py. Trong PostDetailAPIView mình sẽ gọi RetrieveAPIView của GenericsView chỉ có read-only và lấy single model.

from rest_framework.generics import ListAPIView, RetrieveAPIView

...

class PostDetailAPIView(RetrieveAPIView):  
    queryset = Post.objects.all()
    serializer_class = PostSerializer

import và sử dụng PostDetailAPIView vừa tạo trong url:

from .views import PostListAPIView, PostDetailAPIView

...

url(r'^(?P<pk>[\d]+)/$', PostDetailAPIView.as_view(), name='detail'),  

url ở đây sẽ view detail theo id của bài post(pk - primary key).

Giờ chạy thử thôi! Mình sẽ sử dụng để view detail bài post với id là 2 với url: http://127.0.0.1:8000/api/posts/2/

Rất đơn giản phải không ạ? Chỉ cần gọi RetrieveAPIView và đưa nó vào url thôi.
Ngoài việc sử dụng <pk> trong regular expression, các bạn cũng có thể sử dụng slug bằng cách thay url trên bằng:

...

# url(r'^(?P<pk>[\d]+)/$', PostDetailAPIView.as_view(), name='detail'),
url(r'^(?P<slug>[\w-]+)/$', PostDetailAPIView.as_view(), name='detail'),  

và kết quả sẽ như thế này:

Mọi người có thể tham khảo thêm cách dùng slug tại đây.

2. Update và Destroy

Lại lặp lại các bước ở trên thôi.
Thứ nhất là gọi ra đúng APView mình cần. Mình sẽ sử dụng UpdateAPIView cho update(chỉ có update-only) và DestroyAPIView cho delete(chỉ có delete-only).

from rest_framework.generics import (  
    ListAPIView, RetrieveAPIView, UpdateAPIView, DestroyAPIView
)

...

class PostUpdateAPIView(UpdateAPIView):  
    queryset = Post.objects.all()
    serializer_class = PostSerializer

class PostDeleteAPIView(DestroyAPIView):  
    queryset = Post.objects.all()
    serializer_class = PostSerializer

Sau đó là thêm vào url thôi:

from .views import (  
    PostListAPIView, PostDetailAPIView, PostUpdateAPIView, PostDeleteAPIView
)

...

    url(r'^(?P<pk>[\d]+)/edit/$', PostUpdateAPIView.as_view(), name='update'),
    url(r'^(?P<pk>[\d]+)/delete/$', PostDeleteAPIView.as_view(), name='delete'),

Chạy thử với http://127.0.0.1:8000/api/posts/2/edit/http://127.0.0.1:8000/api/posts/2/delete/
ta được kết quả:

Trong 2 kết quả ở trên ta thấy có thông báo: "detail": Method \"GET\" not allwedPostUpdateAPIView, PostDeleteAPIView không có phương thức get trong request HTTP nhưng bạn vẫn có thể edit/delete được(Ở đây là không thể show ra được bài post với id số 2 mình đang thực hiện). Ngoài ra, các bạn có thể đổi UpdateAPIView, DestroyAPIView thành RetrieveUpdateAPIView(read or update), RetrieveDestroyAPIView(read or delete) để có thể get được bài post trước khi thực hiện update hoặc delete.

Với RetrieveUpdateAPIView:

Với RetrieveDestroyAPIView:

Sau đó thử edit bài post số 2

Và thử xóa bài bài post số 4

  • Kết quả thực hiện

3. Create View

Ở đây mình sẽ tạo post create serializer và post create view để thực hiện thao tác tạo post. Trước tiên thêm PostCreateSerializer trong posts/api/serializers.py

class PostCreateSerializer(ModelSerializer):  
    class Meta:
        model = Post
        fields = [
            # 'id',
            'title',
            'content',
            'slug'
        ]

Sau khi đã tạo serializer xong, tiếp tục các bước quen thuộc, tạo ViewAPI thôi. Ở đây mình sẽ tạo PostCreateAPIView.

from rest_framework.generics import (  
    CreateAPIView
)
from .serializers import PostCreateSerializer

...


class PostCreateAPIView(CreateAPIView):  
    queryset = Post.objects.all()
    serializer_class = PostCreateSerializer

Cuối cùng là chỉ cần import PostCreateAPIView vào api/urls.py là xong

from .views import (  
    PostCreateAPIView
)

urlpatterns = [  
...
    url(r'^create/$', PostCreateAPIView.as_view(), name='create'),

]

Đi đến http://127.0.0.1:8000/api/posts/create/ và thử tạo 1 post. Cần chú ý khi tạo post vì trường slug là unique.

Mở rộng ra 1 chút, với phần xử lý slug, bạn có thể xử lý tạo slug ở trong model. Trước khi save vào DB, bạn có thể xử lý title để tạo luôn slug để tránh tạo slug bằng tay. Chi tiết phần xử lý, các bạn có thể tham khảo tại đây.

Như vậy trong bài viết này, mình đã cùng các bạn thao tác CRUD trong Django Rest Framework. Trong phần tiếp theo mình sẽ tiếp tục đi đến phần xử lý với user. Cảm ơn các bạn đã theo dõi.
(Links tham khảo các bài trước của series)

Suýt quên mất, nhắn nhỏ các bạn: Nếu có vẫn gặp vướng mắc trong khi thực hành hoặc có bất kì thắc mắc về Python, Django hay muốn tìm hiểu thêm các thông tin hữu ích, các bạn hãy tham gia group Django (Python) Vietnam để được các admin và thành viên support trực tiếp vấn đề mà bạn gặp phải nhé.

Related article