django restframework restful 风格接口

restful 风格接口 -DRF

是风格 不是标准

  • http、https协议
  • 传输数据类型 json
  • url : 单独的url 比如 http://api.douban.com 或者说 http://www.douban.com/api/
  • 在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。一般来说,数据库中的表都是同种记录的"集合"(collection),所以API中的名词也应该使用复数。
  • get、post、delete、put、patch
    • http://www.qfedu.com/api/users/ get请求 获取所有的用户 list
    • http://www.qfedu.com/api/user/1/ get 请求 获取id 为1 的用户 retrieve
    • http://www.qfedu.com/api/user/ post 新建一个用户 create
    • http://www.qfedu.com/api/user/1/ put 更新id为1 的用户 需要提供用户的所有信息 全量更新 update
    • http://www.qfedu.com/api/user/1/ patch 更新id为1 的用户 只需要提供修改的信息 增量更新 partial_update
    • http://www.qfedu.com/api/user/1/ delete 删除id 为1 的用户 destory
  • 状态码
    • 200 请求成功
    • 201 服务器按照相应的要求进行了操作
    • 400 请求方法有错误 服务器没有U任何的响应
    • 403 禁止访问
    • 401 没有权限
    • 404 找不到
    • 405 请求方法有错误
    • 500 服务器内部错误
  • 接口文档 小幺鸡
    • 接口描述
    • 接口地址
    • 请求方法
    • 提交参数
    • 返回值
    • 返回示例数据

视图函数

  • CBV( class base view ) 类视图
  • FBV (Function Base View) 函数视图

DRF

官网 https://www.django-rest-framework.org/

翻译网站 https://q1mi.github.io/Django-REST-framework-documentation/

安装

pip install djangorestframework

创建 序列化类

HyperlinkedModelSerializerModelSerialize 区别在于使用超链接来表示关系而非主键

ModelSerializer 以id主键作为关系

from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Book
        fields = ('url', 'b_name', 'b_price')
        
class Book2Serializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ('id', 'b_name', 'b_price')
        
class Book3Serializer(serializers.Serializer):
    id =serializers.IntegerField(read_only=True)
    b_name = serializers.CharField()
    b_price = serializers.FloatField()

    def create(self, validated_data):
        return Book.objects.create(**validated_data)

    def update(self, instance, validated_data):
        print(validated_data.get("b_name"))
        print(validated_data.get("b_price"))
        instance.b_name = validated_data.get("b_name") or instance.b_name
        instance.b_price = validated_data.get("b_price") or instance.b_price
        instance.save()
        return instance

视图函数

from rest_framework import viewsets
from .models import Book
from .serializers import BookSerializer,Book2Serializer,Book3Serializer

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = Book3Serializer

urls.py

from rest_framework import routers
from . import views

router = routers.DefaultRouter()

router.register(r'books',views.BookViewSet)

项目url文件

from django.urls import path,include
from front.urls import router
urlpatterns = [
    path('',include(router.urls)),
]

限定请求方法

限定某个接口只能get 或者 post请求 需要分别继承 指定的类

from rest_framework.generics import CreateAPIView,ListAPIView,ListCreateAPIView,RetrieveAPIView,UpdateAPIView 
post 			get 获取所有     get、post 	    获取指定的		更新

# class GameCreatAPIView(CreateAPIView): #只能post请求
#     queryset = Game
#     serializer_class = GameSerializer

# class GameCreatAPIView(ListAPIView): #只能get请求
#     queryset = Game.objects.all()
#     serializer_class = GameSerializer
#path('games/',views.GameCreatAPIView.as_view(),name='create_game')
# class GameCreatAPIView(ListCreateAPIView): #只能get和post请求
#     queryset = Game.objects.all()
#     serializer_class = GameSerializer

#re_path(r'games/(?P\d+)/',views.GameCreatAPIView.as_view(),name='create_game'),

class GameCreatAPIView(RetrieveAPIView): #只能get和post请求
    queryset = Game.objects.all()
    serializer_class = GameSerializer

限定请求方法 通过url进行限定

不是通过 继承 而是通过url地址完成限定

class MovieViewSet(viewsets.ModelViewSet):
    queryset = Movie.objects.all()
    serializer_class = MovieSerializer
    
urlpatterns = [
    re_path(r'games/(?P\d+)/',views.GameCreatAPIView.as_view(),name='create_game'),
    #get post
    #http://127.0.0.1:8088/api/movies/
    re_path(r'^movies/$',views.MovieViewSet.as_view(actions={"get": "list","post": "create"})),
    #get http://127.0.0.1:8088/api/movies/1/
    #put  http://127.0.0.1:8088/api/movies/1/
    #patch http://127.0.0.1:8088/api/movies/1/
    #delete http://127.0.0.1:8088/api/movies/1/
    re_path(r'^movies/(?P\d+)/$', views.MovieViewSet.as_view(actions={"get": "retrieve", "put": "update","patch":"partial_update","delete":"destroy"})),
]

接口的安全

views.py 


class UserCreateApiView(CreateAPIView):#只能post请求
    serializer_class = UserSerializer
    def post(self, request, *args, **kwargs):
        action = request.GET.get('action')
        #http://127.0.0.1:8088/view/users/?action=register
        if action == 'register':
            return self.create(request,*args, **kwargs)
        #http://127.0.0.1:8088/view/users/?action=login
        elif action == 'login':
            return self.do_login(request,*args, **kwargs)
        else:
            raise APIException(detail='只能登录或者注册')
    def do_login(self,request,*args, **kwargs):
        #接收字段
        # u_name = request.POST.get('u_name')
        u_name = request.data.get('u_name')
        m_password = request.POST.get('m_password')
        try:
            user = User.objects.get(u_name=u_name)
        except User.DoesNotExist as e:
            raise NotFound(detail='该用户不存在')

        if user.m_password != m_password:
            raise APIException(detail='密码有误请重新输入')

        #登录成功以后 我们要求必须生成token

        token = uuid.uuid4().hex

        #生成token同时 将其存入缓存中
        cache.set(token,user.id,timeout=60*60*24*7)

        data = {
            'status':status.HTTP_200_OK,
            'msg':"登录成功",
            'token':token
        }
        return Response(data)

    

应用下-> authentications.py 

from django.core.cache import cache
from rest_framework.authentication import BaseAuthentication
from .models import User
#首先根据token从缓存中取出来 没有返回空

#如果有 取出指定的 user.id
#根据user.id 从数据库中取出详细的信息
#判断是否有权限

class UserAuthentication(BaseAuthentication):
    def authenticate(self, request):
        try:
            token = request.GET.get('token')
            user_id = cache.get(token) #根据键 查出值

            user = User.objects.get(pk=user_id) #取出详细的信息
            return user,token
        except Exception as e:
            return None

        
应用-> permissions.py

from rest_framework.permissions import BasePermission

from .models import User

class UserLoginPermission(BasePermission):
    def has_permission(self, request, view):
        return isinstance(request.user,User)
    
    
views.py


from .authentications import UserAuthentication
from .permissions import UserLoginPermission
class MovieViewSet(viewsets.ModelViewSet):
    queryset = Movie.objects.all()
    serializer_class = MovieSerializer
    authentication_classes = UserAuthentication,
    permission_classes = UserLoginPermission,

你可能感兴趣的:(django)