文章目录
写在前面:
官方文档为主,博客为辅。博主建议新人连同官方文档一起看,更有助于理解。看完觉得有收获,记得点赞。
drf是什么?
Django REST framework (官方文档地址)
是在前后端分离的开发模式中,基于Django的RestFul API开发框架。
drf怎么使用
正如django中类视图比函数视图简洁一般,drf很多地方也是有多种编写方式,下文直接使用简洁的一种。
第一步:定义序列化器。
在django项目中,创建serializers.py
文件。
引入模型,定义序列化器:
from rest_framework import serializers
from .models import Books # 引入自己的模型。替换掉相关字段即可。
class BooksSerializer(serializers.ModelSerializer):
class Meta:
model = Books
fields = ['title', 'created_by', 'subject',
'country', 'created_time', 'content']
def create(self, validated_data):
return Books.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.title = validated_data.get('title', instance.title)
instance.created_by = validated_data.get(
'created_by', instance.created_by)
instance.subject = validated_data.get('subject', instance.subject)
instance.country = validated_data.get('country', instance.country)
instance.created_time = validated_data.get(
'created_time', instance.created_time)
instance.content = validated_data.get('content', instance.content)
instance.save()
return instance
*Django REST framework 官网已经有写好的代码。一般情况下复制上面代码,引入自己的模型。替换掉相关字段即可。
第二步:配置settings。
分页:
分页允许您控制每页返回多少个对象。
settings里添加代码:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}
添加app
settings中添加app处加入:rest_framework。
INSTALLED_APPS = [
...
'rest_framework',
]
注意:这条配置,如果还没完成身份验证这一块的代码,先注释掉,不然会报错。
# drf配置
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
}
第三步:编写视图。
直接使用通用类视图:
from .models import Books
from rest_framework import generics
class BookstList(generics.ListCreateAPIView):
queryset = Books.objects.all()
serializer_class = BooksSerializer
class BooksDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Books.objects.all()
serializer_class = BooksSerializer
代码少吧?
可以对比下不使用通用视图的情况:
detail
视图
from rest_framework import mixins
from rest_framework import generics
from .models import Books
from .serializers import BooksSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class BookstDetail(APIView):
def get_object(self, pk):
try:
return Books.objects.get(pk=pk)
except Books.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
book = self.get_object(pk)
serializer = BooksSerializer(book)
return Response(serializer.data)
def put(self, request, pk, format=None):
book = self.get_object(pk)
serializer = BooksSerializer(book, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
book = self.get_object(pk)
book.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
list
视图:
class BooksListView(APIView):
def get(self, request, format=None):
books = Books.objects.all()
serializer = BooksSerializer(books, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = BooksSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
第四步:urls。
和django的urls文件都是一样的。
from django.urls import path
from . import views
from rest_framework.urlpatterns import format_suffix_patterns
urlpatterns = [
path('detail/<int:pk>/', views.BooksDetail.as_view(), name='detail'),
path('books_list/', views.BookstList.as_view(), name='books_list'),
]
urlpatterns = format_suffix_patterns(urlpatterns)
————————————————————— 可以休息一下线 —————————————————————
用户认证
用户认证无非就是两个问题:是否登录,是否有权限操作。当然,别忘了创建了用户。
from rest_framework import permissions
from .permissions import IsOwnerOrReadOnly
class BookstList(generics.ListCreateAPIView):
queryset = Books.objects.all()
serializer_class = BooksSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly]
class BooksDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Books.objects.all()
serializer_class = BooksSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly]
通用视图添加一行代码就可以了。IsAuthenticatedOrReadOnly
IsOwnerOrReadOnly
两个权限即可满足大多数要求。
IsOwnerOrReadOnly
权限需要手动编写:
创建permissions.py
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
return True
# Write permissions are only allowed to the owner of the snippet.
return obj.created_by == request.user
也可以添加一个登录和注销的视图。不需要做更多操作。
urlpatterns += [
path('api-auth/', include('rest_framework.urls')),
]
————————————————————— 可以休息一下线 —————————————————————
视图集和路由器
优点:
代码量更少了,专注于API提供的交互和表示形式。
缺点:
在使用基于类的视图而不是基于函数的视图时,与单独构建视图相比,使用视图集不那么明确。
views更改部分:
原先代码:
from rest_framework import generics
class BookstList(generics.ListCreateAPIView):
queryset = Books.objects.all()
serializer_class = BooksSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly]
class BooksDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Books.objects.all()
serializer_class = BooksSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly]
现在代码:
from rest_framework import viewsets # 不要忘了引入
class BooksViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Books.objects.all()
serializer_class = BooksSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly]
def perform_create(self, serializer):
serializer.save(created_by=self.request.user)
urls更改:
from rest_framework.routers import DefaultRouter
from .views import BooksViewSet
from django.urls import include # 其中一种方法需要引入
router = DefaultRouter()
router.register(r'', BooksViewSet) # 注册路由器
# 加入路由方法一
urlpatterns = [
path('', include(router.urls)),
'···'
]
# 加入路由方法二
urlpatterns += router.urls
# 将viewset绑定到url
books_list = BooksViewSet.as_view({
'get': 'list',
'post': 'create'
})
books_detail = BooksViewSet.as_view({
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy'
})
现在拆解一下上面代码:
第一步,引入相关模块。
第二步,注册路由器。
第三步,添加路由数据。此处有两种方式,但是方法一报错,我选择了方法二。典型的打不过就跑,不丢人。
第四步,将viewset绑定到url。
对,这就结束了。官方文档为主,博客为辅。记得点赞。 这次一定。