zoukankan      html  css  js  c++  java
  • Python之Django rest_Framework

    Django Rest Framework

    一、rest api

       a、api就是接口

            如: - http://www.oldboyedu.com/get_user/

                   - http://www.oldboyedu.com/get_users/

       b、api的两个用途

            1、为别人提供服务

            2、前后端分离

    二、restful

        a、--字面意思:表征状态转移

        b、面向资源编程,对互联网上的任意东西都视为资源

             如:- http://www.oldboyedu.com/get_user/

                    - http://www.oldboyedu.com/get_img/1.png

    普通的API:

        如:

    姑娘列表:
                    http://www.oldboyedu.com/get_girls/
                    http://www.oldboyedu.com/add_girl/
                    http://www.oldboyedu.com/del_girl/1/
                    http://www.oldboyedu.com/update_girl/1/

    restful api:

    姑娘列表:
                    http://www.oldboyedu.com/girls/
                    GET: 获取
                    POST: 添加
                    PUT: 更新
                    DELETE:删除

    三、restful规范

          ---URL

          ---url名词

    路径,视网络上任何东西都是资源,均使用名词表示(可复数)
      https://api.example.com/v1/zoos
      https://api.example.com/v1/animals
      https://api.example.com/v1/employees

          ---status状态码

    200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
    201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
    202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
    204 NO CONTENT - [DELETE]:用户删除数据成功。
    400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
    401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
    403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
    404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
    406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
    410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
    422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
    500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
    
    更多看这里:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
    常用状态码

          ---提交方式

    • GET      :从服务器取出资源(一项或多项)
    • POST    :在服务器新建一个资源
    • PUT      :在服务器更新资源(客户端提供改变后的完整资源)
    • PATCH  :在服务器更新资源(客户端提供改变的属性)
    • DELETE :从服务器删除资源

          ---错误信息

    状态码是4xx时,应返回错误信息,error当做key。
    {
        error: "Invalid API key"
    }

          ---版本

    URL,如:https://api.example.com/v1/
    请求头                                                  跨域时,引发发送多次请求

          ---Hypermedia link,RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。

    {"link": {
      "rel":   "collection https://www.example.com/zoos",
      "href":  "https://api.example.com/zoos",
      "title": "List of zoos",
      "type":  "application/vnd.yourformat+json"
    }}

             ---域名

    https://api.example.com                         尽量将API部署在专用域名(会存在跨域问题)
    https://example.org/api/                        API很简单

             ---过滤,通过在url上传参的形式传递搜索条件

    https://api.example.com/v1/zoos?limit=10:指定返回记录的数量
    https://api.example.com/v1/zoos?offset=10:指定返回记录的开始位置
    https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数
    https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
    https://api.example.com/v1/zoos?animal_type_id=1:指定筛选条件

             ---返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范

    GET /collection:返回资源对象的列表(数组)  
    GET /collection/resource:返回单个资源对象
    POST /collection:返回新生成的资源对象
    PUT /collection/resource:返回完整的资源对象
    PATCH /collection/resource:返回完整的资源对象
    DELETE /collection/resource:返回一个空文档
    - 姑娘:
                    方式一:
                        http://www.oldboyedu.com/girls/
                        http://www.oldboyedu.com/girls/1/
                        GET: 获取
                        POST: 添加
                        PUT: 更新
                        DELETE:删除
                
                   方式二:
                        http://www.oldboyedu.com/girls/
                                                     - 姑娘列表
                        http://www.oldboyedu.com/girl/1/
                                                     - 单独一个

    四、基于Django做API

          ---FBV

          ---CBV

    路由系统:

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^users/', views.users),
    url(r'^user/(d+)', views.user),
    ]

    FBV视图:

    from django.shortcuts import render,HttpResponse
    import json

    def users(request):
    response = {'code':1000,'data':None}
    response['data'] = [
    {'name':'lg','age':19},
    {'name':'mqj','age':20},
    {'name':'wxp','age':5},
    ]
    return HttpResponse(json.dumps(response),status=200)

    def user(request,pk):
    if request.method == "GET":
    return HttpResponse(json.dumps({'name':'lg','age':19}))
    elif request.method == "POST":
    return HttpResponse(json.dumps({'code':1111}))
    elif request.method == "PUT":
    pass
    elif request.method == "DELETE":
    pass

    CBV:

    路由系统:

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
          url(r'^admin/', admin.site.urls),
          url(r'^users/', views.UsersView.as_view()),
          url(r'^user/(d+)', views.UserView.as_view()),
    】

    CBV视图:

    from django.shortcuts import render,HttpResponse
    from django.views import View
    import json
    
    class UsersView(View):
        def get(self,request):
            response = {'code': 1000, 'data': None}
            response['data'] = [
                {'name': 'lg', 'age': 19},
                {'name': 'mqj', 'age': 20},
                {'name': 'wxp', 'age': 5},
            ]
            return HttpResponse(json.dumps(response), status=200)
    
    class UserView(View):
    
        def dispatch(self, request, *args, **kwargs):
    
            # method = request.method.lower()
            # func = getattr(self,method)
            # ret = func()
            # return ret
            ret = super(UserView,self).dispatch(request,*args, **kwargs)
            return ret
    
        def get(self,request,pk):
            print(request,type(request))
            return HttpResponse(json.dumps({'name': 'lg', 'age': 19}))
    
        def post(self,request,pk):
            return HttpResponse(json.dumps({'name': 'lg', 'age': 19}))
    
        def put(self,request,pk):
            return HttpResponse(json.dumps({'name': 'lg', 'age': 19}))
    
        def delete(self,request,pk):
            return HttpResponse(json.dumps({'name': 'lg', 'age': 19}))

    五、 基于Django Rest Framework框架实现

        a、安装:pip3 install djangorestframework -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com

        b、基本流程

    url.py
      
      from django.conf.urls import url, include
      from web.views.s1_api import TestView
     
      urlpatterns = [
          url(r'^test/', TestView.as_view()),
      ]
    views.py
    from rest_framework.views import APIView from rest_framework.response import Response class TestView(APIView): def dispatch(self, request, *args, **kwargs): """ 请求到来之后,都要执行dispatch方法,dispatch方法根据请求方式不同触发 get/post/put等方法 注意:APIView中的dispatch方法有好多好多的功能 """ return super().dispatch(request, *args, **kwargs) def get(self, request, *args, **kwargs): return Response('GET请求,响应内容') def post(self, request, *args, **kwargs): return Response('POST请求,响应内容') def put(self, request, *args, **kwargs): return Response('PUT请求,响应内容')

        c、基于Token的用户认证

    url.py:

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    from app02 import views as app02_view
    urlpatterns = [
            # django rest framework
        url(r'^auth/', app02_view.AuthView.as_view()),
        url(r'^hosts/', app02_view.HostView.as_view()),
    
    ]
    url.py

    views.py

    from django.views import View
    
    from rest_framework.views import APIView
    from rest_framework.authentication import SessionAuthentication
    from rest_framework.authentication import BasicAuthentication
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.request import Request
    from rest_framework.exceptions import APIException
    from rest_framework.response import Response
    
    
    from app02 import models
    import hashlib
    import time
    
    # class MyBasicAuthentication(BasicAuthentication):
    #     def authenticate_credentials(self, userid, password, request=None):
    #         if userid == 'alex' and password == '123':
    #             return ('alex','authaaaaaaaaaaaa')
    #         raise APIException('认证失败')
    
    class AuthView(APIView):
        authentication_classes=[]
        def get(self,request):
            """
            接收用户名和密码
            :param request: 
            :return: 
            """
            ret = {'code':1000,'msg':None}
    
            user = request.query_params.get('user')
            pwd = request.query_params.get('pwd')
    
            obj = models.UserInfo.objects.filter(username=user,password=pwd).first()
            if not obj:
                ret['code'] = 1001
                ret['msg'] = "用户名或密码错误"
                return Response(ret)
            # 创建随机字符串
            ctime = time.time()
            key = "%s|%s" %(user,ctime)
            m = hashlib.md5()
            m.update(key.encode('utf-8'))
            token = m.hexdigest()
    
            # 保存到数据
            obj.token = token
            obj.save()
    
            ret['token'] = token
            return Response(ret)
    
    
    class HostView(APIView):
    
        def get(self,request,*args,**kwargs):
            # 原来request对象,django.core.handlers.wsgi.WSGIRequest
            # 现在的request对象,rest_framework.request.Request
            self.dispatch
            print(request.user)
            print(request.auth)
            return Response('主机列表')
    views.py
    django-rest-framework
                - 认证
                    - 局部
                        class MyAuthentication(BaseAuthentication):
    
                            def authenticate(self, request):
                                # return None ,我不管
                                token = request.query_params.get('token')
                                obj = models.UserInfo.objects.filter(token=token).first()
                                if obj:
                                    return (obj.username,obj)
                                raise APIException('用户认证失败')
                                
                                
                        class AuthView(APIView):
                            authentication_classes=[MyAuthentication,]
                    - 全局
                         #配置文件
                        REST_FRAMEWORK = {
                            'UNAUTHENTICATED_USER': None,
                            'UNAUTHENTICATED_TOKEN': None,
                            "DEFAULT_AUTHENTICATION_CLASSES": [
                                "app02.utils.MyAuthentication",
                            ],
                        }
    
                        
                        class HostView(APIView):
    
                            def get(self,request,*args,**kwargs):
                                # 原来request对象,django.core.handlers.wsgi.WSGIRequest
                                # 现在的request对象,rest_framework.request.Request
                                print(request.user)
                                print(request.auth)
                                return HttpResponse('主机列表')
  • 相关阅读:
    Linux 升级内核开启 TCP BBR 有多大好处
    rbd-mirror配置指南-单向备份
    python调用dll方法
    Python调用Google翻译
    Python Sleep休眠函数
    用Python监听鼠标和键盘事件
    python编码(七)
    SceneControl+AE+鼠标滚轮缩放
    基于SceneControl单击查询功能的实现
    基于SceneControl的三维GIS开发
  • 原文地址:https://www.cnblogs.com/mengqingjian/p/8418469.html
Copyright © 2011-2022 走看看