django-rest-framework学习笔记

## RESTful
-软件架构风格,是一种思想
-用在客户端和服务端这种模型中
-实现的就是前后端分离
-理解
	-表现层状态转换
	-表征性状态转移
	-缺少主语 资源(resource)
	-客户端要实现状态转换 通过请求谓词
		-GET
		-POST
		-PUT
		-DELETE
		-PATCH
		
**-api设计原则**
	-协议http(s)
	-专属域名或前缀
	-可以包含版本
	-在querystring中包含过滤信息
	-路径通常是名词复数
	-传输格式JSON
	-尽量带有超链接
	-认证使用OAuth2.0
	
**-简单实现**
	-针对一个接口的不同请求方式进行不同的处理
	-GET/collection/
	-GET/collection/id/
	-POST/collection/
	-POST/collection/id
	-DELECT/collection/id
	
**-接口测试,模拟请求**
	-pycharm自带的
	-postman
	-httpie

## 重量级RESTful
**-django-rest-framework**
**-REST难点**

	-模型序列化
		-正向序列化
			-将模型转化成JSON
		-反向序列化
			-将JSON转换成模型
			
**-序列化器serializers**
	-Serializer
		-原生序列化
		-需要手动编写每个序列化的字段
		-手动实现对象创新和更新
	-ModelSerializer
		-模型序列化
		-只需指定模型和字段(fields)
	-HeperLinkedModelSerializer
		-带超链接的模型序列化
		-指定序列化的模型和字段
		-字段扩充了url
-helloREST
	-序列化器
	-视图函数viewsets
		-viewsets.ModelViewSet
		-CBV
		-视图集合
		-直接集成了
			-对象的创建
			-对象的列表查询
			-对象的单个查询
			-对象的修改
			-对象的删除
	-路由router
		-routers.DefaultRouter
		-将viewsets注册在此
		-实际上生成了多个路由
		-include到urlpatterns
		-数据一下就实现了CRUD
	-记得在INSTALLED_APPS添加rest_frameword
	-runserver
		-所有api变成可视化
		-超链接
		-对数据集合实现了
			-路由/users/,/groups/
			-get
			-post
		-对单个数据实现了
			-路由 /users/id/,/groups/id/
			-get
			-post
			-put
			-delete
			-patch
		-viewsets做了视图函数的实现
		-router做了路由的注册
## 双R
	-request
		-rest_framework.request
		-重新定义了一个类
		-扩充了django中的request
		-将django里的request作为了自己的一个属性_request
		-属性和方法
			-content_type
			-stream
			-query_params
			-data
				-同时兼容POST/PUT/PATCH
			-user
				-可以直接在请求上获取用户
				-相当于在请求上添加一个属性,用户对象
			-auth
				-认证
				-相当于在请求上添加了一个属性,属性值是token

	-response
		-HttpResponse的子类
	-status
		-常量类
	-View的包装
		-@api_view
			-通过装饰器的形式修改既有视图函数
			-可以添加请求控制
		-APIView
			-继承自View
			-封装了一堆函数
			-as_view的重写
			-dispatch重写
				-初始化request
				-构建一个新的request
				-使用django中的request和一些过滤类生成了rest_framework中的request
			-初始化工具
			-认证
			-权限
			-节流
## ApiView
	-renderer_classes
		-渲染的类
	-paeser_classes
		-解析转换的类
	-authentication_classes
		-认证的类
		-认证成功返回一个元组
		-第一个元素user
		-第二个元素auth,token
	-throttle_classes
		-节流的类
		-控制请求频率的类
		-判断请求频率是否被允许
	-permission_classes
		-权限的类
		-所有权限都满足才正常
	-content_negotiation_class
		-内容过滤的类
	-metadata_class
		-元信息的类
	-versioning_class
		-版本控制的类
	-csrf_exempt全局豁免
-子类
	-GenericAPIView
		-增加了模型的获取操作
	-CreateAPIView
		-创建的类视图
		-继承自GenericAPIView
		-继承自CreateModelMixin
		-实现了post进行创建
	-ListAPIView
		-列表的类视图
		-继承自GenericAPIView
		-继承自ListModelMixin
		-实现了get
	-RetrieveAPIView
		-查询单个数据的类视图
		-继承自GenericAPIView
		-继承自RetrieveModelMixin
		-实现了get
	-DestroyAPIView
		-删除数据的类视图
		-继承自GenericAPIView
		-继承自
		-实现了delete
	-UpdateAPIView
		-更新数据的类视图
		-继承自GenericAPIView
		-继承自UpdateModelMixin
		-实现了put,patch
	-ListCreateAPIView
		-获取列表数据,创建数据的类视图
		-实现了get,post
	-RetrieveUpdateAPIView
		-获取单个数据,更新单个数据的类视图
		-实现了get,put,patch
	-RetrieveDestroyAPIView
		-获取单个数据,删除单个数据的类视图
		-实现了get,delete
	RetrieveUpdateDestroyAPIView
		-获取单个数据,更新单个数据,删除单个数据的类视图
		-实现了get,put,patch,delete
-mixins
	-CreateModelMixin
	-ListModelMixin
		-list
		-查询结果集,添加分页,帮助序列化
	-RetrieveModelMixin
		-获取单个对象并进行序列化
	-DestroyModelMixin
		-destroy
			-获取单个对象
			-调用执行删除
			-返回respon 状态码204
		-perform_destroy
			-默认是模型的delete
			-如果是数据的逻辑删除
				-重写进行保存
	-UpdateModelMixin
		-update
			-获取对象,合法验证
			-执行更新
		-perform_update
		-partial—_update
			-差量更新,对应的是patch
-viewsets

## api例子

models.py

from django.db import models

class Game(models.Model):
	g_name=models.CharField(max_length=32)
	g_price=models.FloatField(default=0)


Serializers.py

from rest_framework import serializers
from App.models import Game

class GameSerializer(serializers.HeperLinkedModelSerializer):
	class Meta:
		model=Game
		fields=("url","id","g_name","g_price")

views.py

from rest_framework import ListCreateAPIView
from rest_framework import RetrieveUpdateDestroyAPIView

class GamesView(ListCreateAPIView):
	serializer_class=GameSerializer
	queryset=Game.objects.all()

class GameView(RetrieveUpdateDestroyAPIView):
	serializer_class=GameSerializer
	queryset=Game.objects.all()

App/urls.py

from App import views

urlpatterns=[
	url(r'^games/$',views.GamesView.as_view()),
	url(r'^games/(?P\d+)/',views.GameView.as_view(),name='game-detail'),
]


project/urls.py

urlpatterns=[
	url(r'^app/',include('App.urls')),
]


## 用户模块
-用户注册
	-restful 
	-数据开始
		-模型、数据库
		-创建用户
			-用户身份
				-管理员
				-普通
				-删除用户

models.py

class UserModel(models.Model):
	u_name=models.CharField(max_length=32,unique=True)
	u_password=models.CharField(max_length=256)
	is_delete=models.BooleanField(default=False)
	is_super=models.BooleanField(default=False)


serializer.py

from rest_framework import serializers
from App.models import UserModel

class UserSerializer(serializer.HeperLinkedModelSerializer);
	class Meta:
		model=UserModel
		fields=('url','id','u_name','u_password','is_super')

views.py

from App.models import UserModel
from App.serializers import UserSerializer
from rest_framework import status
from rest_framework.generics import ListCreateAPIView
from rest_framework.response import Response
from rest_framework import exception

class UsersAPIView(ListCreateAPIView):
	serializer_class=UserSerializer
	queryset=UserModel.objects.all()

class UserAPIView(ListCreateAPIView):
	serializer_class=UserSerializer
	queryset=UserModel.objects.all()

	def create(self,request,*args,**kwargs):
		serializer=self.get_serializer(data=request.data)
		serializer.is_valid(raise_exception=True)
		self.perform_create(serializer)

		data=serializer.data
		u_name=data.get('u_name')
		if u_name in SUPER_USERS:
			print('创建超级用户')
			u_id=data.get('id')
			user=UserModel.objects.get(pk=u_id)
			user.is_super=True
			user.save()
			data.update({
     'is_super':True})
		#返回更新后的数据
		headers=self..get_success_headers(serializer.data)
		return Response(data,status.HTTP_201_CREATED,headers=headers)


App/urls.py

from App import views

urlpatterns=[
	url(r'^users/$',views.UsersAPIView.as_view()),
	url(r'^users/(?P\d+)/$',views.UserAPIView.as_view(),name='usermodel-detail'),
]

-超级用户注册
settings.py

SUPER_USERS=('admin','root')

-用户登录
	-验证用户名密码
	-生成用户令牌
	-出现和注册共用post冲突
		-添加action
		-path/?action=login
		-path/?action=register
		-异常捕获尽量精确

在class UserAPIView 中添加函数def post

class UserAPIView(ListCreateAPIView):
	serializer_class=UserSerializer
	queryset=UserModel.objects.all()

	from App.auth import UserAuth
	authentication_classes=(UserAuth,#用户登录认证类

	from App.permissions import IsSuperUser
	permission_classes=(IsSuperUser,)  #用户权限类

	def get(self,request,*args,**kwargs):
		if isinstance(request.user,UserModel):
			return self.list(request,*args,**kwargs)
		else:
			raise exceptions.NotAuthenticated


	def post(self,request,*args,**kwargs):
		action=request.query_params.get('action')
		if action=='register':
			return self.create(request,*args,**kwargs)
		elif action=='login':
			u_name=request.data.get['u_name']
			u_password=request.data.get['u_password']
			try:
				user=UserModel.objects.get(u_name=u_name)
				if user.u_password==u_password:
					token=uuid.uuid4().hex
					#使用缓存来存储用户token,别忘记配置缓存
					cache.set(token,user.id)

					data={
     
					'msg':'login success',
					'status':200,
					'token':token,
					}
					return Response(data)
				else:
					raise exceptions.AuthenticationFailed
			except UserModel.DoesNotExist:
				raise exceptions.NotFound
		else:
			raise exceptions.ValidationError

-用户认证 
	-BaseAuthentication
		-authenticate
			-认证成功会返回一个元组
				-第一个元素是user
				-第二个元素是令牌

auth.py

from django.core.cache import cache
from rest_framework.authentication import BaseAuthentication
from App.models import UserModel

class UserAuth(BaseAuthentication):
	def authenticate(self,request):
		if request.method=='GET':
			token=request.query_params.get('token')
			try:
				u_id=cache.get(token)
				user=UserModel.objects.get(pk=u_id)
				return user,token
			except:
				return

-用户权限
-BasePermission
	-has_permission
		-是否具有权限
		-true拥有权限
		-false不具有权限
-用户认证和权限
	-直接配置在试图函数上就ok了


permissions.py

from rest_framework.permissions import BasePermission
class IsSuperUser(BasePermission):
	def has_permission(self,request,view):
		if request.method=='GET':
			if isinstance(request.user,UserModel):
				return request.user.is_super
			return False
		return True


## 用户和收货地址的级联
-存在级联数据
-用户和收货地址
-节流

-分析
-数据开始
	-模型定义
	-用户和收货地址 一对多
		-用户表
		-地址表
			-ForeignKey
	-序列化
		-级联数据如何实现序列化
	-节流

models.py

from django.db import models
class UserModel(models.Model):
	u_name=models.CharField(max_length=16,unique=True)
	u_password=models.CharField(max_length=256)

class Address(models.Model):
	a_address=models.CharField(max_length=128)
	a_user=models.ForeignKey(UserModel,null=True,blank+True)


serializers.py

from rest_framework import serializers

class AddressSerializer(serializers.HeperLinkedModelSerializer):
	class Meta:
		model=Address
		fields=('url','id','a_address')

class UserSerialize(serializers.HeperLinkedModelSerializer):
	address_set=AddressSerializer(many=True,read_only=True)
	class Meta:
		model=UserModel
		fields=('url','id','u_name','u_password','address_set')

views.py

from rest_framework.generics import CreateAPIView
from App.models import UserModel
from App.serializers import UserSerializer

class UsersAPIView(CreateAPIView):
	serializer_class=UserSerializer
	queryset=UserModel.objects.all()
	def post(self,request,*args,**kwargs):
		action=request.query_params.get('action')
		if action=='login':
			u_name=request.data.get('u_name')
			u_password=request.data.get('u_password')
			try:
				user=UserModel.objects.get(u_name=u_name)
				if user.u_password != u_password:
					raise exceptions.AuthenticationFailed
				token = uuid.uuid4().hex
				cache.set(token,user.id,timeout=60*60)
				data={
     
					'msg':'login success',
					'status':200,
					'token':token,
				}
				return Response(data)
			except UserModel.DoesNotExist:
				raise exceptions.NotFound

		elif action=='register':
			return self.create(request,*args,**kwargs)
		else:
			raise exceptions.ParseError

class UserAPIView(RetrieveAPIView):
	serializer_class=UserSerializer
	queryset=UserModel.objects.all()
	authentication_classes=(LoginAuthentication,)
	permission_classes=(LoginPermission,)

	def retrieve(self,request,*args,**kwargs):
		instance=self.get_object()
		if instance.id != request.user.id:
			raise exceptions.AuthenticationFailed
		serializer=self.get_serializer(instance)
		return Response(serializer.data) 

class AddressAPIView(viewsets.ModelViewSet):
	serializer_class=AddressSerializer
	queryset=Address.objects.all()
	authentication_classes=(LoginAuthentication,)
	permission_classes=(LoginPermission,)

	def create(self,request,*args,**kwargs):
		serializer=self.get_serializer(data=request.data)
		serializer.is_valid(raise_exception=True)
		self.perform_create(serializer)
		headers=self.get_success_headers(serializer.data)
		user=request.user
		address_id=serializer.data.get('id')
		address=Address.objects.get(pk=address_id)
		address.a_user=user
		address.save()

		return Response(serializer.data,status=status.HTTP_201_CREATED,headers=headers)

	def list(self,request,*args,**kwargs):
		queryset=self.filter_queryset(self.get_queryset())
		page=self.paginate_queryset(queryset)
		if page is not None:
			serializer=self.get_serializer(page,,many=True)
			return self.get_painated_response(serializer.data)
		serializer=self.get_serializer(queryset,many=True)
		return Response(serializer.data)



App/urls.py

from App import views

urlpatterns=[
	url(r'^users/$',views.UsersAPIView.as_view()),
	url(r'^users/(?P\d+)/$',views.UserAPIView.as_view(),name='usermodel-detail'),
	url(r'^address/$',views.AddressAPIView.as_view(
		{
     
			'post':'create',
			'get':'list',
		}
		)),
	url(r'^address/(?P\d+)/$',views.AddressAPIView.as_view(
		{
     
			'get':'retrieve',
		}
		),name='address-detail')
]


auth.py

from rest_framework.authentication import BaseAuthentication
class LoginAuthentication(BaseAuthentication):
	def authenticate(self,request):
		#if request.method='GET':
		try:
			token=request.query_params.get('token')
			user_id=cache.get(token)
			user=UserModel.objects.get(pk=user_id)
			return user,token
		except Exception:
			return

permissions.py

from rest_framework.permissions import BasePermission

class LoginPermission(BasePermission):
	def has_permission(self,request,view):
		return isinstance(request.user,UserModel)

你可能感兴趣的:(笔记,python,django,restful)