-软件架构风格,是一种思想
-用在客户端和服务端这种模型中
-实现的就是前后端分离
-理解
-表现层状态转换
-表征性状态转移
-缺少主语 资源(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
**-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做了路由的注册
-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
-初始化工具
-认证
-权限
-节流
-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
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
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):
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)