REST framework

文章目录

    • restful协议
    • restframework基于restful协议开发
      • 序列化类
      • request拓展
    • restframework视图
    • token拓展
    • 认证、权限、频率
      • 全局认证
    • 分页器
    • 解析器
    • 根据url指定渲染器
      • 返回json数据
      • 表格
      • form表单
      • API+JSON
      • 渲染拓展

restful协议

--- 一切皆是资源,操作只是请求方式
 
---book表增删改查
    /books/                 books
	/books/add/             addbook
	/books/(\d+)/change/    changebook
	/books/(\d+)/delete/    delbook
	 
---book表增删改查
	/books/     ----get            books       ----  返回当前所有数据
	/books/     ----post           books       ----  返回提交数据 

	/books/(\d+)----get            bookdetail  ----  返回当前查看的单条数据 
	/books/(\d+)----put            bookdetail  ----  返回更新数据 
	/books/(\d+)----delete         bookdetail  ----  返回空数据
	# 示例
	from django.views import View
		class  Books(View):			
			def get(self,request):
			  pass  # 查看所有书籍				  
		    def post(self,request):
			  pass  # 添加书籍			  
			  
		class  BooksDetail(View):
		    def get(self,request,id):
			  pass  # 查看具体书籍		 
		    def put(self,request,id):
			  pass  # 更新某本书籍				  
		    def delete(self,request,id):
			  pass  # 删除某本书籍	

restframework基于restful协议开发

pip install django
pip install restframework

序列化类

# 方式1:
publish_list=list(Publish.objects.all().values("name","email"))
return HttpResponse(json.dumps(publish_list))

# 方式2:
from django.forms.models import model_to_dict
publish_list = Publish.objects.all()
temp=[]
for obj in publish_list:
    temp.append(model_to_dict(obj))
return HttpResponse(json.dumps(temp))

# 方式3:
from django.core import serializers
publish_list = Publish.objects.all()
ret = serializers.serialize("json",publish_list)
return HttpResponse(ret)

# 方法4
from rest_framework import serializers
# 继承类serializers.Serializer,为queryset,model对象做序列化
class PublishSerializers(serializers.Serializer):
	name = serializers.CharField()
	email = serializers.CharField()
	
from rest_framework.response import Response
publish_list = Publish.objects.all()
ps = PublishModelSerializers(publish_list, many=True)
return Response(ps.data)


# 多对多restframe序列化
from rest_framework import serializers

class BookSerializers(serializers.Serializer):
	title = serializers.CharField(max_length=32)
	price = serializers.IntegerField()
	pub_date = serializers.DateField()
	# 多对多字段自定义
	publish=serializers.CharField(source="publish.name")# 跨表显示name
	#authors=serializers.CharField(source="authors.all")
	authors = serializers.SerializerMethodField()
	def get_authors(self,obj):
		temp=[]
		for obj in obj.authors.all():
			temp.append(obj.name)
		return temp
# 相当于下面
'''
序列化BookSerializers(book_list,many=True)过程:
	 temp=[]
	 for obj in book_list:
		 temp.append({
			"title":obj.title,
			"price":obj.price,
			"pub_date":obj.pub_date,
			#"publish":str(obj.publish), # 表Publish 定义的返回字段的值
			"publish":str(obj.publish.name), # source="publish.name"
			#"authors":obj.authors.all,
			"authors": get_authors(obj)
		 })

'''

# 方法5	更简单的默认restframe序列化
from rest_framework import serializers
class BookModelSerializers(serializers.ModelSerializer):
class Meta:
    model = Book
    fields = "__all__"


# 案例
# 路由函数
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
	url(r'^admin/', admin.site.urls),	
	url(r'^publishes/$', views.PublishView.as_view(),name="publish"), 
	url(r'^publishes/(?P\d+)/$', views.PublishDetailView.as_view(),name="detailpublish"),
	url(r'^books/$', views.BookView.as_view(),name="books"),
	url(r'^books/(\d+)/$', views.BookDetailView.as_view(),name="detailbook"),
]

# serializer.py
from rest_framework import serializers
# 继承ModelSerializer,可以实现序列化、数据校验、存储功能
class BookModelSerializers(serializers.ModelSerializer):
	class Meta:
		model = Book
		fields = "__all__"
	# 自定义字段,显示链接
	publish=serializers.HyperlinkedIdentityField(
			# 显示链接的路由名
			view_name="detailpublish",
			# 获取当前对象对应的字段值
			lookup_field="publish_id",
			# 该值放在组pk的位置
			lookup_url_kwarg="pk"
	)

# 视图函数
from rest_framework.response import Response # Response可以返回格式化对象
from app01.serilizer import *
class BookView(APIView):
	# get返回所有对象
	def get(self,request):
		book_list=Book.objects.all()
		# 自定义字段,显示连接,序列化时必须加上context={'request': request}
		bs=BookModelSerializers(book_list,many=True,context={'request': request})
		return Response(bs.data)
	# post返回发送的对象
	def post(self,request):
		# post请求的数据
		bs=BookModelSerializers(data=request.data)
		# 校验数据
		if bs.is_valid():
			print(bs.validated_data)
			bs.save()# create方法存储数据到数据库
			return Response(bs.data)
		else:
			return Response(bs.errors)

class BookDetailView(APIView):

	def get(self,request,id):
		book=Book.objects.filter(pk=id).first()
		bs=BookModelSerializers(book,context={'request': request})
		return Response(bs.data)
	# put返回编辑对象
	def put(self,request,id):
		book=Book.objects.filter(pk=id).first()
		bs=BookModelSerializers(book,data=request.data)
		if bs.is_valid():
			bs.save()
			return Response(bs.data)
		else:
			return Response(bs.errors)
	# delete返回None
	def delete(self,request,id):
		Book.objects.filter(pk=id).delete()
		return Response()

request拓展

request.POST	为url携带数据或form携带数据
request.body	携带数据的二进制模式,可以是urlencode、form、json

rest_framework.views的request特殊取值
from rest_framework.views import APIView
class PublishView(APIView):
	def get(self,request):
		# 序列组件
		class PublishSerializers(serializers.Serializer):
		name = serializers.CharField()
		email = serializers.CharField()
		
		publish_list = Publish.objects.all()
		ps = PublishSerializers(publish_list, many=True)
		return Response(ps.data)
		
	def post(self,request):
		# APIView新的request支持的操作
		print("request.data",request.data)# 只能接受post携带数据,json数据
		print("request.GET",request.GET)# GET携带的数据,同下
		print("request.GET",request._request.GET)# GET携带的数据
		print("request.data type",type(request.data))

restframework视图

# 基于功能的视图
from rest_framework import mixins
from rest_framework import generics
# 继承List、Create、APIView
class AuthorView(mixins.ListModelMixin,mixins.CreateModelMixin,generics.GenericAPIView):
	# 下面2个为固定参数必须写
	queryset=Author.objects.all() # 所有对象
	serializer_class =AuthorModelSerializers # 序列化的类方法

	def get(self,request, *args, **kwargs):
		# self.list()方法即,序列化对象,返回序列化后的对象
		return self.list(request, *args, **kwargs)
	def post(self,request, *args, **kwargs):
		return self.create(request, *args, **kwargs)
		
# 继承Retrieve、Destroy、Update、APIView
class AuthorDetailView(mixins.RetrieveModelMixin,mixins.DestroyModelMixin,mixins.UpdateModelMixin,generics.GenericAPIView):
	queryset = Author.objects.all()
	serializer_class = AuthorModelSerializers

	def get(self,request,*args, **kwargs):
		return self.retrieve(request,*args, **kwargs)
	def delete(self,request,*args, **kwargs):
		return self.destroy(request,*args, **kwargs)
	def put(self,request,*args, **kwargs):
		return self.retrieve(request,*args, **kwargs)


# 基于通用类
from rest_framework import mixins
from rest_framework import generics
# 在ListCreateAPIView里面有get对应list方法,post对应create方法
class AuthorView(generics.ListCreateAPIView):
	queryset=Author.objects.all()
	serializer_class =AuthorModelSerializers

class AuthorDetailView(generics.RetrieveUpdateDestroyAPIView):
	queryset = Author.objects.all()
	serializer_class = AuthorModelSerializers
	
# 基于视图集
# 路由需要改
url(r'^authors/$', views.AuthorModelView.as_view({"get":"list","post":"create"}),name="author"),
url(r'^authors/(?P\d+)/$', views.AuthorModelView.as_view({"get":"retrieve","put":"update","delete":"destroy"}),name="detailauthor"),
# 视图函数
from rest_framework import viewsets
from app01.utils import TokenAuth

class AuthorModelView(viewsets.ModelViewSet):
	queryset = Author.objects.all()
	serializer_class = AuthorModelSerializers

token拓展

def get_random_str(user):
	import hashlib,time
	ctime=str(time.time())
	# 密钥
	md5=hashlib.md5(bytes(user,encoding="utf8"))
	# md5加密ctime
	md5.update(bytes(ctime,encoding="utf8"))
	return md5.hexdigest()

from .models import User
class LoginView(APIView):
	def post(self,request):
		name=request.data.get("name")
		pwd=request.data.get("pwd")
		user=User.objects.filter(name=name,pwd=pwd).first()
		res = {"state_code": 1000, "msg": None}
		
		if user:
			# 获取token
			random_str=get_random_str(user.name)
			token=Token.objects.update_or_create(user=user,defaults={"token":random_str})
			res["token"]=random_str
		else:
			res["state_code"]=1001 #错误状态码
			res["msg"] = "用户名或者密码错误"

		import json
		return Response(json.dumps(res,ensure_ascii=False))

认证、权限、频率

from rest_framework import exceptions
from rest_framework.authentication import BaseAuthentication
from rest_framework.permissions import BasePermission
from .models import *

class TokenAuth(BaseAuthentication):
	def authenticate(self,request):
		token = request.data.get("token")
		token_obj = Token.objects.filter(token=token).first()
		if not token_obj:
			raise exceptions.AuthenticationFailed("验证失败123!")
		else:
			return token_obj.user.name,token_obj.token
			
class MyPermission(BasePermission):
	message = '无权访问'
	def has_permission(self,request,view):  # 此时的self是view视图对象
		if request.user:
			return True  #如果不是匿名用户就说明有权限
		return False  #否则无权限

class AdminPermission(BasePermission):
	message = '无权访问'
	def has_permission(self, request, view):  # 此时的self是view视图对象
		if request.user=='haiyun':
			return True  # 返回True表示有权限
		return False #返回False表示无权限

# 自定义频率限制
VISIT_RECORD = {}
class MyThrottle(object):
	def __init__(self):
		self.history = None

	def allow_request(self, request, view):
		"""
		自定义频率限制60秒内只能访问三次
		"""
		# 获取用户IP
		ip = request.META.get("REMOTE_ADDR")
		timestamp = time.time()
		if ip not in VISIT_RECORD:
			VISIT_RECORD[ip] = [timestamp, ]
			return True
		history = VISIT_RECORD[ip]
		self.history = history
		history.insert(0, timestamp)
		# 超过60秒的登录记录删除
		while history and history[-1] < timestamp - 60:
			history.pop()
		# 判断是否超过3次访问记录
		if len(history) > 3:
			return False
		else:
			return True

	def wait(self):
		"""
		限制时间还剩多少
		"""
		timestamp = time.time()
		return 60 - (timestamp - self.history[-1])
	
	class AuthorModelView(viewsets.ModelViewSet):
		# 当前试图使用
		authentication_classes = [TokenAuth,]
		permission_classes = [MyPermission,AdminPermission]
		throttle_classes = [MyThrottle, ]
		queryset = Author.objects.all()
		serializer_class = AuthorModelSerializers

全局认证

修改settings,将自己编写的认证类
REST_FRAMEWORK = {
	"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.TokenAuth",],
	"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
	"DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ],
	"DEFAULT_THROTTLE_CLASSES": ["app01.utils.MyThrottle", ]
}

分页器

from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination
class MyPageNumberPagination(PageNumberPagination):
	# 每页显示数据几条
	page_size = 2
	# 数据关键字
	page_query_param = 'page'
	# 临时修改每页显示数据条数的关键字
	page_size_query_param="size"
	# 临时修改每页显示数据的最大值
	max_page_size=10
	
class MyLimitOffsetPagination(LimitOffsetPagination):
	# 每页显示数据条数
	default_limit=3
	
class BookView(APIView):
	parser_classes = [JSONParser,FormParser]

	def get(self,request):
		book_list=Book.objects.all()
		# 分页
		pnp=MyPageNumberPagination() 	?page=2
		# page为第几页
		# pnp=MyLimitOffsetPagination() ?offset=2&limit=2
		# offset为跳过几个数据,limit为显示几条数据
		# 固定调用方式,返回值为queryset对象
		books_page=pnp.paginate_queryset(book_list,request,self)
		bs=BookModelSerializers(books_page,many=True)
		return Response(bs.data)

解析器

# 四种解析器
from rest_framework.parsers import JSONParser,FormParser,MultiPartParser,FileUploadParser
class BookView(APIView):
	# 加上parser_classes便可指定解析器,解析指定类型数据
	parser_classes = [JSONParser,FormParser]
def get(self,request):	
	pass

    # 分页

    pnp=MyLimitOffsetPagination()
    books_page=pnp.paginate_queryset(book_list,request,self)

    bs=BookModelSerializers(books_page,many=True,context={'request': request})
    return Response(bs.data)

根据url指定渲染器

返回json数据

http://127.0.0.1:8000/test/?format=json
http://127.0.0.1:8000/test.json
http://127.0.0.1:8000/test/ 
# 路由函数
from django.conf.urls import url, include
from web import views
urlpatterns = [
	url(r'^test/$', views.TestView.as_view()),
	url(r'^test\.(?P[a-z0-9]+)', views.TestView.as_view()),
]
# 视图函数
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers

from rest_framework.renderers import JSONRenderer
from .. import models

class TestSerializer(serializers.ModelSerializer):
	class Meta:
		model = models.UserInfo
		fields = "__all__"

class TestView(APIView):
	# 渲染器JSON
	renderer_classes = [JSONRenderer, ]

	def get(self, request, *args, **kwargs):
		user_list = models.UserInfo.objects.all()
		ser = TestSerializer(instance=user_list, many=True)
		return Response(ser.data)

表格

http://127.0.0.1:8000/test/?format=admin
http://127.0.0.1:8000/test.admin
http://127.0.0.1:8000/test/ 
# 路由函数
from django.conf.urls import url, include
from web import views
urlpatterns = [
	url(r'^test/$', views.TestView.as_view()),
	url(r'^test\.(?P[a-z0-9]+)', views.TestView.as_view()),
]
# 视图函数
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers

from rest_framework.renderers import AdminRenderer
from .. import models

class TestSerializer(serializers.ModelSerializer):
	class Meta:
		model = models.UserInfo
		fields = "__all__"

class TestView(APIView):
	# 表格渲染器
	renderer_classes = [AdminRenderer, ]

	def get(self, request, *args, **kwargs):
		user_list = models.UserInfo.objects.all()
		ser = TestSerializer(instance=user_list, many=True)
		return Response(ser.data)

form表单

http://127.0.0.1:8000/test/?format=form
http://127.0.0.1:8000/test.form
http://127.0.0.1:8000/test/ 
# 路由函数
from django.conf.urls import url, include
from web import views
urlpatterns = [
	url(r'^test/$', views.TestView.as_view()),
	url(r'^test\.(?P[a-z0-9]+)', views.TestView.as_view()),
]
# 视图函数
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers

from rest_framework.renderers import HTMLFormRenderer
from .. import models

class TestSerializer(serializers.ModelSerializer):
	class Meta:
		model = models.UserInfo
		fields = "__all__"

class TestView(APIView):
	# 表单渲染器
	renderer_classes = [HTMLFormRenderer, ]

	def get(self, request, *args, **kwargs):
		user_list = models.UserInfo.objects.all().first()
		ser = TestSerializer(instance=user_list, many=False)
		return Response(ser.data)

API+JSON

http://127.0.0.1:8000/test/?format=api
http://127.0.0.1:8000/test.api
http://127.0.0.1:8000/test/ 
# 路由函数
from django.conf.urls import url, include
from web import views
urlpatterns = [
	url(r'^test/$', views.TestView.as_view()),
	url(r'^test\.(?P[a-z0-9]+)', views.TestView.as_view()),
]
# 视图函数
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers

from rest_framework.renderers import JSONRenderer
from rest_framework.renderers import BrowsableAPIRenderer
from .. import models

class TestSerializer(serializers.ModelSerializer):
	class Meta:
		model = models.UserInfo
		fields = "__all__"
		
# 自定义api+json渲染器
class CustomBrowsableAPIRenderer(BrowsableAPIRenderer):
	def get_default_renderer(self, view):
		return JSONRenderer()

class TestView(APIView):
	# 引用自定义渲染器
	renderer_classes = [CustomBrowsableAPIRenderer, ]

	def get(self, request, *args, **kwargs):
		user_list = models.UserInfo.objects.all().first()
		ser = TestSerializer(instance=user_list, many=False)
		return Response(ser.data, template_name='user_detail.html')

渲染拓展

路由都可改为,即可自动实现
from django.conf.urls import url,include
from rest_framework import routers
from app01 import views

routers=routers.DefaultRouter()
routers.register("authors",views.AuthorModelView)

urlpatterns = [
	url(r'', include(routers.urls)),
]

你可能感兴趣的:(Django)