Rest-framework使用
下载 pip install djangorestframework
(1) APIView (*****)
流程:
from rest_framework.views import APIView
APIView(view) 继承了view 在原来基础上扩展功能
APIView中as_view super了viwe中的as_view
但是 as_viwe中的dispath 用的是 APIview从写的dispath
在APIview从写的dispath中从新封装request对象 增加了 权限,认证,频率组件
(2) 序列化组件(*****)
from django.core.serializers import serialize # Django的序列化组件
from rest_framework import serializers DRF的序列化组件
定义类使用
class BookSerializer(serializers.Serializer):
title = serializers.CharField( max_length=32)
price =serializers.DecimalField(max_digits=5,decimal_places=2)
在接口类使用
a = BookSerializer('查询出所有的书籍',many=Ture) many默认False意思是序列化一个
return Response(a.data)
post提交数据
a=CourseSerializer(data=request.data)
if a.is_valid(): # 校验
Book.objects.create(**request.data) 不能使用save
return Response(a.data) # 序列化数据
else:
return Response(a.errors) # 序列化错误信息
一对多字段
publish_email=serializers.CharField(max_length=32,source="publish.email")
添加source字段会显示这个里面的值
多对多字段
#authors=serializers.CharField(max_length=32,source="authors.all") 是一个QuerySet不使用
authors=serializers.SerializerMethodField() 使用这个
def get_authors(self,obj):
ret=[]
for i in obj.authors.all():
ret.append(i.name)
return ret
使用 ModelSerializer
class BookSerializer(serializers.ModelSerializer):
class Meta:
model=Book
# fields=["title","price"]
fields="__all__"
# publish=serializers.CharField(max_length=32,source="publish.name")
# authors=serializers.SerializerMethodField()
# def get_authors(self,obj):
# ret=[]
# for i in obj.authors.all():
# ret.append({"name":i.name,"pk":i.pk})
# return ret
post提交
def post(self,request):
serializer=BookSerializer(data=request.data,many=False)
if serializer.is_valid():
serializer.save() # create操作 可以使用
return Response(serializer.data)
else:
return Response(serializer.errors)
如果我查询1条数据()get)的时候 冲突
所以在写一个视图类 让get put delete放入
修改一条数据(put)
def put(self,request,id):
edit_obj = Book.objects.get(pk=id)
serializer=BookSerializer(data=request.data,instance=edit_obj)
if serializer.is_valid():
serializer.save() # edit_obj.update(request.data)
return Response(serializer.data)
else:
return Response(serializer.errors)
(3) 视图类(mixin)(*****)
mixin 混合类
from rest_framework.mixins import
ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin
查询 添加 更新 删除 查询单条
from rest_framework import generics generics.GenericAPIView使用它调用as_view
class PublishView(ListModelMixin,CreateModelMixin,generics.GenericAPIView):
queryset = Publish.objects.all()
serializer_class = PublishSerializer
def get(self,request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self,request, *args, **kwargs):
return self.create(request, *args, **kwargs)
在使用单条查询的时候必须写 PK值
url(r'^publishes/(?P<pk>\d+)/', views.SPublishView.as_view()),
在类中不用写id
class SPublishView(UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin,generics.GenericAPIView):
queryset = Publish.objects.all()
serializer_class = PublishSerializer
def get(self,request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
使用generics.ListCreateAPIView 和 generics.RetrieveUpdateDestroyAPIView 进行封装
class AuthorsView(generics.ListCreateAPIView):
queryset = Author.objects.all()
serializer_class = AuthorSerializer
class SAuthorsView(generics.RetrieveUpdateDestroyAPIView):
queryset = Author.objects.all()
serializer_class = AuthorSerializer
终极封装 ModelViewSet 必须在url的as_view中写入制定参数
from rest_framework.viewsets import ModelViewSet
class AuthorsView(ModelViewSet):
queryset = Author.objects.all()
serializer_class = AuthorSerializer
url(r'^authors/$', views.AuthorsView.as_view({"get":"list","post":"create"})),
url(r'^authors/(?P<pk>\d+)/', views.AuthorsView.as_view({"get":"retrieve","delete":"destroy","put":"update"})),
(4) 认证组件
准备2张表
class User(models.Model):
user=models.CharField(max_length=32)
pwd=models.CharField(max_length=32)
type=((1,"VIP"),(2,"SVIP"),(3,"SSSVIP"))
user_type=models.IntegerField(choices=type)
class UserToken(models.Model):
user=models.OneToOneField("User")
token=models.CharField(max_length=128)
在每次登陆时 如果没有就创建 否则就 更新Token值
import uuid
random_str = uuid.uuid4()
if user:
UserToken.objects.update_or_create(user=user, defaults={"token": random_str})
response["user"] = user.user
response["token"] = random_str
在接口类中使用 authentication_classes = [UserAuth,]
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
class UserAuth(BaseAuthentication):
def authenticate(self,request):
token=request.query_params.get("token")
usertoken=UserToken.objects.filter(token=token).first()
if usertoken:
return usertoken.user,usertoken.token
else:
raise AuthenticationFailed("认证失败!")
(5) 权限组件
判断等级进行判断
在接口类中使用 permission_classes = [SVIPPermission]
from rest_framework.permissions import AllowAny
from rest_framework.permissions import BasePermission
class SVIPPermission(BasePermission):
message="您没有访问权限!"
def has_permission(self,request,view):
if request.user.user_type >= 2: #判断
return True
return False
(6) 频率组件
在接口类中使用 throttle_classes = [VisitThrottle]
from rest_framework.throttling import BaseThrottle
class VisitThrottle(BaseThrottle):
def allow_request(self,request,view):
"""
限制IP每分钟访问不能超过3次
:param request:
:param view:
:return:
"""
print(self.get_ident(request)) #拿到IP
remote_addr = request.META.get('REMOTE_ADDR') #拿到IP
print("REMOTE_ADDR",remote_addr)
return False
可以使用自带的频率控制类
from rest_framework.throttling import SimpleRateThrottle
class VisitThrottle(SimpleRateThrottle):
scope="visit_rate"
def get_cache_key(self,request, view):
return self.get_ident(request)
需要在settings中设置
REST_FRAMEWORK={
"DEFAULT_THROTTLE_CLASSES": ("app01.utils.throttle_class.VisitThrottle",),
"DEFAULT_THROTTLE_RATES": {
"visit_rate": "10/m",
},
}
(7) 分页组件
from rest_framework.pagination import PageNumberPagination
class MyPageNumberPagination(PageNumberPagination):
page_size=2 #每页显示多少条
page_query_param="page_num" # get取到的页面名称 &page_num=1
page_size_query_param="size" # 临时调整 &size = 3 每页显示3条
max_page_size=5 # 最大可以临时调整5条
print(request.user,request.auth)
book_list=Book.objects.all() # 对所有书分页
pnp=MyPageNumberPagination() # 分页器对象
paged_book_list=pnp.paginate_queryset(book_list,request) # 对什么分页
serializer=BookSerializer(paged_book_list,many=True) # 序列化分页后的数据
(8) 解析器组件(*****)
from rest_framework.parsers import JSONParser,FormParser,FileUploadParser
在类中设置 parser_classes = [] 自定义格式
根据客户端发送到后端的数据 是用的json格式还是urlencoded格式
根据格式服务器根据那种格式解
发送的请求体格式 a=1&b=2 urlencoded格式 在form表单中entype中设置格式 或
ajax也是可以用contenttype设置
发送到服务器我根据什么解格式
(9) 响应器组件
默认支持2种响应
当浏览器去访问时候返给你一个页面
用postman发给的是json数据
(10) url注册器
from rest_framework import routers
router = routers.DefaultRouter()
router.register("authors",views.AuthorsView) #根据名字 和视图类就可以访问
放到url中 from django.conf.urls import url,include
url(r'^', include(router.urls)),