Belajar Django: DRF ListCreateAPIView Custom Queryset & Post
Masih lanjut yang terkait ListCreateAPIView, pada kode yang kemarin saya hanya mendeklarasikan saja beberapa hal di views dan secara ajaib semua sudah berjalan, contoh dalam kode, saya hanya mendeklarasikan queryset yang digunakan adalah dari model Post, dan di sana saya mengambil semuanya tanpa terkecuali. Lalu bagiamana jika kita ingin mengambil post yang publish-nya bernilai True dan dibuat lebih dari kemarin misalnya, yang jauh-jauh hari gak perlu dimunculin. Caranya mudah, kita cukup membuat method “get_queryset()” di dalam class dan ubah kode jadi berikut
from rest_framework.generics import ListCreateAPIView from .models import Post, Category from .serializers import PostSerializer from rest_framework import filters from .pagination import MyPagination from datetime import datetime, timedelta class PostListCreate(ListCreateAPIView): serializer_class = PostSerializer filter_backends = (filters.SearchFilter,) search_fields = ('title', 'content') pagination_class = MyPagination def get_queryset(self): yesterday = datetime.now() - timedelta(1) return Post.objects.filter(publish=True, created_at__gt=yesterday)
Dengan kode di atas saya membuat mengganti atribut queryset dengan method get_queryset(), dan hasilnya saat kita coba akses list
{ "status": 200, "message": "Success", "links": { "next": null, "previous": null, "total_page": 1 }, "total": 2, "total_on_page": "2 from 2", "data": [ { "id": 5, "title": "Something 3", "content": "modelss", "publish": true, "created_at": "2019-07-23T15:55:29.197989Z", "updated_at": "2019-07-23T15:55:29.198038Z", "category_id": { "id": 1, "title": "Cat 1" } }, { "id": 6, "title": "Something 4", "content": "modelss", "publish": true, "created_at": "2019-07-23T15:55:45.226811Z", "updated_at": "2019-07-23T15:55:45.226858Z", "category_id": { "id": 1, "title": "Cat 1" } } ] }
Manipulasi POST
Misalkan dalam model Post saya ingin menambahkan nilai slug jadi kalau ada judul “Belum Ada Judul” akan memiliki slug “belum-ada-judul”, tapi karena saat ini belum ada slug di model mari kita tambahkan dimunculin
Ubah model Post menjadi seperti berikut
class Post(models.Model): category_id=models.ForeignKey(Category, on_delete=models.CASCADE) title=models.CharField(max_length=200) slug=models.CharField(max_length=200, null=True, blank=True) content=models.TextField() publish=models.BooleanField(default=False) created_at=models.DateTimeField(auto_now_add=True) updated_at=models.DateTimeField(auto_now=True) def __str__(self): return self.title
Buat migration dan migrate
python manage.py makemigrations python manage.py migrate
Jika berhasil kolom slug sudah ditambahkan di table.
Lalu untuk manipulasi post ubah views menjadi alias menambahkan method post()
from rest_framework.generics import ListCreateAPIView from .models import Post, Category from .serializers import PostSerializer from rest_framework import filters from .pagination import MyPagination from datetime import datetime, timedelta class PostListCreate(ListCreateAPIView): serializer_class = PostSerializer filter_backends = (filters.SearchFilter,) search_fields = ('title', 'content') pagination_class = MyPagination def get_queryset(self): yesterday = datetime.now() - timedelta(1) return Post.objects.filter(publish=True, created_at__gt=yesterday) def post(self, request, *args, **kwargs): if 'title' in request.data: title = request.data['title'] request.data['slug'] = title.replace(' ','-') return self.create(request, *args, **kwargs)
Hasilnya
{ "id": 7, "title": "Belum Ada Judul", "slug": "Belum-Ada-Judul", "content": "Belum ada content", "publish": true, "created_at": "2019-07-25T17:21:32.563235Z", "updated_at": "2019-07-25T17:21:32.563335Z", "category_id": { "id": 1, "title": "Cat 1" } }
Note:
Jika post dilakukan dari content-type form-data, request.data di method POST imutable alias tidak bisa diapa-apain lagi, kalau content-type nya JSON maka request.data mutable.
Referensi: https://www.django-rest-framework.org/api-guide/generic-views/