Như các bạn biết, Django REST framework là một framework tuyệt vời để phát triển web với python, hiện tại nó đang rất phổ biến và được nhiều người tiếp cận. Cụ thể các ông lớn đã áp dụng công nghệ này chẳng hạn như Instagram, Pinterest, Youtube, Spotify, Bitbucket,...
Tiếp theo, bạn cần thêm một số thiết lập quan trọng trong settings.py:
Để sử dụng các .env, ví dụ thay thế các giá trị bên trong settings.py sử dụng các giá trị trong .env như sau:
Bây giờ, bạn chỉ cần migrations và xem kết quả trên database.
Cách 2: Sử dụng SerializerMethodField
Cập nhật serializer_class là FileListSerializer trong views.py:
1. Tắt pagination tự động
Khi bạn làm việc với DRF ModelViewSet, có lẽ bạn sẽ dùng đến pagination, nhưng bạn chỉ muốn thêm pagination cho một list view nhất định, còn list khác thì không. Để tắt pagination trên mỗi class cụ thể, bạn có thể dùng cách sau:
class MyClassBasedView(ModelViewSet):
pagination_class = None
...
2. Environment variables
Trong DRF, chúng ta cũng có thể setup các biến môi trường, chẳng hạn như bạn muốn tạo ra một các biến môi trường cho database name, hay các secret key,...
Đầu tiên, bạn cần cài đặt Django Environ, bằng lệnh sau:
$ pip install django-environ
import environ
# Initialise environment variables
env = environ.Env()
environ.Env.read_env()
Bây giờ, bạn cần tạo file .env để thêm các variables của bạn, ví dụ trong file .env có nhưng khai báo sau:SECRET_KEY=h^z13$qr_s_wd65@gnj7a=xs7t05$w7q8!x_8zsld#
DATABASE_NAME=postgresdatabase
DATABASE_USER=alice
DATABASE_PASS=supersecretpassword
DATABASES = {
`default`: {
`ENGINE`: `django.db.backends.postgresql_psycopg2`,
`NAME`: env(`DATABASE_NAME`),
`USER`: env(`DATABASE_USER`),
`PASSWORD`: env(`DATABASE_PASS`),
}
}
3. Lưu trạng thái sau mỗi lần create/update/delete
Trong DRF, bạn có thể lưu lịch sử sau mỗi lần tương tác với model, cụ thể là khi thực hiện create/ update/ delete dữ liệu. Bạn có thể dễ dàng làm điều này khi sử dụng django-simple-history. Cụ thể như các bước dưới đây:
Đâu tiên, ta cần install django-simple-history với command sau:
$ pip install django-simple-history
Tiếp theo cần thiết lập bằng cách thêm simple_history vào INSTALLED_APPS:
INSTALLED_APPS = [
# ...
'simple_history',
]
Các historical models có thể theo dõi ai đã thực hiện sau mỗi thay đổi. Để tự động cập nhật, ta cần thêm HistoryRequestMiddleware vào Django settings:MIDDLEWARE = [
# ...
'simple_history.middleware.HistoryRequestMiddleware',
]
Bây giờ, để theo dõi lịch sử cho một model, ta chỉ cần thêm simple_history.models.HistoricalRecords vào model đó. Cụ thể ta có ví dụ sau:from django.db import models
from simple_history.models import HistoricalRecords
class Poll(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
history = HistoricalRecords()
class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
history = HistoricalRecords()
4. Truy cập item detail bằng slug thay vì Id
Mặc định khi bạn xem chi tiết item thì sẽ truy cập theo Id, với slug nó cũng là duy nhất, và để truy cập chi tiết item theo slug, dưới đây là giải pháp:
Trước tiên, ta cần thêm lookup_field trong serializer:
class ItemSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Item
fields = ('url', 'slug', 'title', 'item_url')
lookup_field = 'slug'
extra_kwargs = {
'url': {'lookup_field': 'slug'}
}
Và trong view sẽ như sau:class ItemViewSet(viewsets.ModelViewSet):
queryset = Item.objects.all()
serializer_class = ItemSerializer
lookup_field = 'slug'
5. Additional field trong serializer
Để bổ sung các trường không thuộc trong thiết kế của bạn, chẳng hạn bạn muốn thêm một trường fullname với fullname được gộp lại từ firstname và lastname.
Để làm điều này, ta có 2 cách như dưới đây:
Cách 1: Sử dụng readonly field với source
# models.py
class Employees(models.Model):
created = models.DateTimeField(auto_now_add=True)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
@property
def full_name(self):
return self.first_name + self.last_name
# serializers.py
class EmployeeSerializer(serializers.ModelSerializer):
full_name = serializers.Field(source='full_name')
class Meta:
model = Employees
fields = ('first_name','last_name', 'full_name')
class EmployeeSerializer(serializers.ModelSerializer):
full_name = serializers.SerializerMethodField('get_full_name')
def get_full_name(self, obj):
return obj.first_name + obj.last_name
class Meta:
model = Employees
fields = ('first_name','last_name', 'full_name')
6. Return results from multiple models
Đây là một tips khá hay, khi bạn muốn trả về nhiều models trong một method, ví dụ bạn có một Timeline và khi get list, bạn cần lấy về lượng Tweet lên artical và list Article:
Đây là 2 cách khi sử dụng với ModelViewSet và ListAPIView.
Cách 1: Sử dụng ModelViewSet:
class TimelineViewSet(viewsets.ModelViewSet):
def list(self, request):
queryset = list(itertools.chain(Tweet.objects.all(), Article.objects.all()))
serializer = TimelineSerializer(queryset, many=True)
return Response(serializer.data)
Cách 2: Sử dụng ListAPIView:
class TimeLineList(generics.ListAPIView):
serializer_class = TimeLineSerializer
def get_queryset(self):
return list(itertools.chain(Tweet.objects.all(), Article.objects.all()))
7. Upload multiple files
Để thực hiện upload nhiều files trong DRF, mình giới thiệu các bạn giải pháp sau:
Thêm FileListSerializer trong serializers.py:
class FileListSerializer ( serializers.Serializer ) :
image = serializers.ListField(
child=serializers.FileField( max_length=100000,
allow_empty_file=False,
use_url=False )
)
def create(self, validated_data):
blogs=Blogs.objects.latest('created_at')
image=validated_data.pop('image')
for img in image:
photo=Photo.objects.create(image=img,blogs=blogs,**validated_data)
return photo
class PhotoSerializer(serializers.ModelSerializer):
class Meta:
model = Photo
read_only_fields = ("blogs",)
class PhotoViewSet(viewsets.ModelViewSet):
serializer_class = FileListSerializer
parser_classes = (MultiPartParser, FormParser,)
queryset=Photo.objects.all()
8. Ẩn endpoint trong SwaggerUI
Để ẩn một số endpoint tùy chỉnh bên trong SwaggerUI, các bạn có thể set lại swagger_schema:
class InvoicesView(APIView):
@swagger_auto_schema(swagger_schema=None)
def get(self, request, **kwargs):
...
Lời kết
Trong đây là những tips cơ bản hay gặp trong quá trình bạn làm việc với DRF, những hàm hữu dụng sẽ có trong các bài tiếp theo. Mong bài viết hữu ích với các bạn.
Hieu Ho.