首页 > 其他分享 >第一节:drf入门规范

第一节:drf入门规范

时间:2023-06-20 18:55:23浏览次数:41  
标签:入门 models request 第一节 api https import 序列化 drf

一 Web应用模式

在开发Web应用中,有两种应用模式:

1.1 前后端不分离

image.png

1.2 前后端分离

image.png

二 API接口

为了在团队内部形成共识、防止个人习惯差异引起的混乱,我们需要找到一种大家都觉得很好的接口实现规范,而且这种规范能够让后端写的接口,用途一目了然,减少双方之间的合作成本。

通过网络,规定了前后台信息交互规则的url链接,也就是前后台信息交互的媒介

Web API接口和一般的url链接还是有区别的,Web API接口简单概括有下面四大特点

  • url:长得像返回数据的url链接

  • 请求方式:get、post、put、patch、delete

    • 采用get方式请求上方接口
  • 请求参数:json或xml格式的key-value类型数据

    • ak:6E823f587c95f0148c19993539b99295
    • region:上海
    • query:肯德基
    • output:json
  • 响应结果:json或xml格式的数据

    • 上方请求参数的output参数值决定了响应数据的格式
    • 数据
# xml格式
https://api.map.baidu.com/place/v2/search?ak=6E823f587c95f0148c19993539b99295&region=%E4%B8%8A%E6%B5%B7&query=%E8%82%AF%E5%BE%B7%E5%9F%BA&output=xml
#json格式
https://api.map.baidu.com/place/v2/search?ak=6E823f587c95f0148c19993539b99295&region=%E4%B8%8A%E6%B5%B7&query=%E8%82%AF%E5%BE%B7%E5%9F%BA&output=json
{
    "status":0,
  	"message":"ok",
    "results":[
        {
            "name":"肯德基(罗餐厅)",
            "location":{
                "lat":31.415354,
                "lng":121.357339
            },
            "address":"月罗路2380号",
            "province":"上海市",
            "city":"上海市",
            "area":"宝山区",
            "street_id":"339ed41ae1d6dc320a5cb37c",
            "telephone":"(021)56761006",
            "detail":1,
            "uid":"339ed41ae1d6dc320a5cb37c"
        }
      	...
		]
}

三 接口测试工具:Postman

Postman是一款接口调试工具,是一款免费的可视化软件,同时支持各种操作系统平台,是测试接口的首选工具。

Postman可以直接从官网:https://www.getpostman.com/downloads/下载获得,然后进行傻瓜式安装。

  • 工作面板

image.png

  • 简易的get请求

image.png

  • 简易的post请求

image.png

  • 案例:请求百度地图接口

image.png

四 RESTful API规范

image.png
REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征性状态转移)。 它首次出现在2000年Roy Fielding的博士论文中。

RESTful是一种定义Web API接口的设计风格,尤其适用于前后端分离的应用模式中。
这种风格的理念认为后端开发任务就是提供数据的,对外提供的是数据资源的访问接口,所以在定义接口时,客户端访问的URL路径就表示这种要操作的数据资源。
事实上,我们可以使用任何一个框架都可以实现符合restful规范的API接口。

4.1 数据的安全保障

  • url链接一般都采用https协议进行传输

注:采用https协议,可以提高数据交互过程中的安全性

4.2 url中带API标识

注:看到api字眼,就代表该请求url链接是完成前后台数据交互的

4.3 url中带版本信息

注:url链接中的v1、v2就是不同数据版本的体现(只有在一种数据资源有多版本情况下)

4.4 数据即是资源,均使用名词(可复数)

注:一般提倡用资源的复数形式,在url链接中尽量不要出现操作资源的动词,错误示范:https://api.baidu.com/delete-user

4.5 资源操作由请求方式决定(method)

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

4.7 响应状态码

4.7.1 正常响应

  • 响应状态码2xx
    • 200:常规请求
    • 201:创建成功

4.7.2 重定向响应

  • 响应状态码3xx
    • 301:永久重定向
    • 302:暂时重定向

4.7.3 客户端异常

  • 响应状态码4xx
    • 403:请求无权限
    • 404:请求路径不存在
    • 405:请求方法不存在

4.7.4 服务器异常

  • 响应状态码5xx
    • 500:服务器异常

4.8 错误处理,应返回错误信息,error当做key

{
    error: "无权限操作"
}

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

GET /collection:返回资源对象的列表(数组)
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档

4.10 需要url请求的资源 需要访问资源的请求链接

# Hypermedia API,RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么
{
  	"status": 0,
  	"msg": "ok",
  	"results":[
        {
            "name":"肯德基(罗餐厅)",
            "img": "https://image.baidu.com/kfc/001.png"
        }
      	...
		]
}

比较好的接口返回

# 响应数据要有状态码、状态信息以及数据本身
{
  	"status": 0,
  	"msg": "ok",
  	"results":[
        {
            "name":"肯德基(罗餐厅)",
            "location":{
                "lat":31.415354,
                "lng":121.357339
            },
            "address":"月罗路2380号",
            "province":"上海市",
            "city":"上海市",
            "area":"宝山区",
            "street_id":"339ed41ae1d6dc320a5cb37c",
            "telephone":"(021)56761006",
            "detail":1,
            "uid":"339ed41ae1d6dc320a5cb37c"
        }
      	...
		]
}

四 序列化

api接口开发,最核心最常见的一个过程就是序列化,所谓序列化就是将数据的格式进行转换,序列化可以分两个阶段:

序列化: 把我们识别的数据转换成指定的格式提供给别人。

例如:我们在django中获取到的数据默认是模型对象,但是模型对象数据无法直接提供给前端或别的平台使用,所以我们需要把数据进行序列化,变成字符串或者json数据,提供给别人。

反序列化:把别人提供的数据转换/还原成我们需要的格式。

例如:前端js提供过来的json数据,对于python而言就是字符串,我们需要进行反序列化换成模型类对象,这样我们才能把数据保存到数据库中。

五 Django Rest_Framework

核心思想: 缩减编写api接口的代码

Django REST framework是一个建立在Django基础之上的Web 应用开发框架,可以快速的开发REST API接口应用。在REST framework中,提供了序列化器Serialzier的定义,可以帮助我们简化序列化与反序列化的过程,不仅如此,还提供丰富的类视图、扩展类、视图集来简化视图的编写工作。REST framework还提供了认证、权限、限流、过滤、分页、接口文档等功能支持。REST framework提供了一个API 的Web可视化界面来方便查看测试接口。
image.png
官方文档:https://www.django-rest-framework.org/
github: https://github.com/encode/django-rest-framework/tree/master

特点

  • 提供了定义序列化器Serializer的方法,可以快速根据 Django ORM 或者其它库自动序列化/反序列化;
  • 提供了丰富的类视图、Mixin扩展类,简化视图的编写;
  • 丰富的定制层级:函数视图、类视图、视图集合到自动生成 API,满足各种需要;
  • 多种身份认证和权限认证方式的支持;[jwt]
  • 内置了限流系统;
  • 直观的 API web 界面;
  • 可扩展性,插件丰富

六 环境安装与配置

DRF需要以下依赖:

  • Python (2.7, 3.2, 3.3, 3.4, 3.5, 3.6)
  • Django (1.10, 1.11, 2.0)

DRF是以Django扩展应用的方式提供的,所以我们可以直接利用已有的Django环境而无需从新创建。(若没有Django环境,需要先创建环境安装Django)

6.1 安装DRF

前提是已经安装了django,建议安装在虚拟环境

# mkvirtualenv drfdemo -p python3
# pip install django

pip install djangorestframework --upgrade
pip install pymysql

6.1.1 创建django项目

cd ~/Desktop
django-admin startproject drfdemo

使用pycharm打开项目,设置虚拟环境的解析器,并修改manage.py中的后缀参数。

6.2 添加rest_framework应用

settings.pyINSTALLED_APPS中添加’rest_framework’。

INSTALLED_APPS = [
    ...
    'rest_framework',
]

接下来就可以使用DRF提供的功能进行api接口开发了。在项目中如果使用rest_framework框架实现API接口,主要有以下三个步骤:

  • 将请求的数据(如JSON格式)转换为模型类对象
  • 操作数据库
  • 将模型类对象转换为响应的数据(如JSON格式)

接下来,我们快速体验下四天后我们学习完成drf以后的开发代码。接下来代码不需要理解,看步骤。

6.3 体验drf完全简写代码的过程(了解)

6.3.1. 创建模型操作类

class Student(models.Model):
    # 模型字段
    name = models.CharField(max_length=100,verbose_name="姓名")
    sex = models.BooleanField(default=1,verbose_name="性别")
    age = models.IntegerField(verbose_name="年龄")
    class_null = models.CharField(max_length=5,verbose_name="班级编号")
    description = models.TextField(max_length=1000,verbose_name="个性签名")

    class Meta:
        db_table="tb_student"
        verbose_name = "学生"
        verbose_name_plural = verbose_name

为了方便测试,所以我们可以先创建一个数据库。

create database students charset=utf8;

6.3.1.1 执行数据迁移

把students子应用添加到INSTALL_APPS中
image.png

初始化数据库连接

安装pymysql
pip install pymysql

主引用中__init__.py设置使用pymysql作为数据库驱动

import pymysql

pymysql.install_as_MySQLdb()

settings.py配置文件中设置mysql的账号密码

DATABASES = {
    # 'default': {
    #     'ENGINE': 'django.db.backends.sqlite3',
    #     'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    # },
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': "students",
        "HOST": "127.0.0.1",
        "PORT": 3306,
        "USER": "root",
        "PASSWORD":"123",
    },
}

终端下,执行数据迁移。

python manage.py makemigrations
python manage.py migrate

错误列表

# 执行数据迁移 python manage.py makemigrations 报错如下:

image.png
解决方案:

注释掉 backends/mysql/base.py中的35和36行代码。

image.png

# 执行数据迁移发生以下错误:

image.png
解决方法:
backends/mysql/operations.py146行里面新增一个行代码:
image.png

6.3.2. 创建序列化器

例如,在django项目中创建学生子应用。

python manage.py startapp students

在syudents应用目录中新建serializers.py用于保存该应用的序列化器。

创建一个StudentModelSerializer用于序列化与反序列化。

# 创建序列化器类,回头会在试图中被调用
class StudentModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Student
        fields = "__all__"
  • model 指明该序列化器处理的数据字段从模型类BookInfo参考生成
  • fields 指明该序列化器包含模型类中的哪些字段,’all‘指明包含所有字段

6.3.3. 编写视图

在students应用的views.py中创建视图StudentViewSet,这是一个视图集合。

from rest_framework.viewsets import ModelViewSet
from .models import Student
from .serializers import StudentModelSerializer
# Create your views here.
class StudentViewSet(ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

  • queryset 指明该视图集在查询数据时使用的查询集
  • serializer_class 指明该视图在进行序列化或反序列化时使用的序列化器

6.3.4. 定义路由

在students应用的urls.py中定义路由信息。

from . import views
from rest_framework.routers import DefaultRouter

# 路由列表
urlpatterns = []

router = DefaultRouter()  # 可以处理视图的路由器
router.register('students', views.StudentViewSet)  # 向路由器中注册视图集

urlpatterns += router.urls  # 将路由器中的所以路由信息追到到django的路由列表中

最后把students子应用中的路由文件加载到总路由文件中

from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path("stu/",include("students.urls")),
]

6.3.5. 运行测试

运行当前程序(与运行Django一样)

python manage.py runserver

在浏览器中输入网址127.0.0.1:8000,可以看到DRF提供的API Web浏览页面:
image.png
1)点击链接127.0.0.1:8000/stu/students 可以访问获取所有数据的接口,呈现如下页面:
image.png
2)在页面底下表单部分填写学生信息,可以访问添加新学生的接口,保存学生信息:
image.png
点击POST后,返回如下页面信息:
image.png
3)在浏览器中输入网址127.0.0.1:8000/stu/students/5/,可以访问获取单一学生信息的接口(id为5的学生),呈现如下页面:

image.png
4)在页面底部表单中填写学生信息,可以访问修改学生的接口
image.png
点击PUT,返回如下页面信息:
image.png
5)点击DELETE按钮,可以访问删除学生的接口
image.png
返回,如下页面:
image.png

七 CBV源码分析

# cbv写法:
	1 视图中写视图类,继承View,写跟请求方式同名的方法
    	class BookView(View):
            def get(self,request):
                return 四件套
     2 在路径用写
    	path('books/', BookView.as_view())
        
        
        
# 如上写法,为什么能够执行

# 前置条件:前端请求,一旦路径匹配成功,就会执行  BookView.as_view()(request传入,)
# 入口在  BookView.as_view()--->执行结果---》View中有个as_view类的绑定方法
    @classmethod
    def as_view(cls, **initkwargs):
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            res=self.dispatch(request, *args, **kwargs)
            return res
        return view
    
# 执行结果是view 的内存地址: 请求来了,执行view(request)
	path('books/', view)
    
# 执行 View类中的as_view方法中的内层的view函数,路由匹配成功,本质是在执行
	self.dispatch(request, *args, **kwargs)
    # self是谁的对象?BookView的对象
    # 去BookView中dispatch,找不到,去父类,View中找到了
    
    
# View这个类的dispatch
    def dispatch(self, request, *args, **kwargs):
        # request.method.lower() 如果是get请求,  ‘get’ 在这个列表里面
        if request.method.lower() in self.http_method_names:
            # handler=getattr(BookView的对象,'get')   
            # handler就是BookView类中的get方法
            handler = getattr(self, request.method.lower())
        else:
            handler = self.http_method_not_allowed
        # 执行 BookView类中的get方法 (request)
        return handler(request, *args, **kwargs)
    
# 最终本质跟写fbv的执行流程一样
# 最终结论:什么请求方式,就会执行视图类中的什么方法

八 drf基本使用及request源码分析

8.2.1 APIView

# as_view()
	# 核心走了父类as_view
	view = super(APIView, cls).as_view(**initkwargs)
    # 返回的是局部禁用csrf认证的view视图函数
    return csrf_exempt(view)
    
# dispatch(self, request, *args, **kwargs)
	# 二次封装request对象
	request = self.initialize_request(request, *args, **kwargs)
    # 自定义request规则
    self.initial(request, *args, **kwargs)
    
# initialize_request(self, request, *args, **kwargs)
	# 原生request封装在request._request
    
# initial(self, request, *args, **kwargs)
	# 认证
	self.perform_authentication(request)
    # 权限
    self.check_permissions(request)
    # 频率
    self.check_throttles(request)

8.2.2 Request对象

image.png

九、写5个接口的几种方法

1 用CBV写

models.py

from django.db import models


# Create your models here.
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.IntegerField()

views.py

from django.http import JsonResponse
from django.views import View
from app01.models import Book
import json


# Create your views here.


class BookView(View):
    #取全部书籍
    def get(self, request):
        book_list = Book.objects.all()
        books = []
        for book in book_list:
            books.append({'name': book.name, 'price': book.price})
        return JsonResponse({'code': 100, 'msg': '成功', 'result': books})
	#添加书籍
    def post(self, request):
        name = request.POST.get('name')
        price = request.POST.get('price')
        Book.objects.create(name=name, price=price)
        return JsonResponse({'code': 100, 'msg': '成功'})


class BookDetailView(View):
    #查找一本书籍
    def get(self, request, id):
        book_obj = Book.objects.filter(pk=id).first()
        book = {'name': book_obj.name, 'price': book_obj.price}
        return JsonResponse({'code': 200, 'msg': '成功', 'result': book})
	#更新一本书
    def put(self, request, id):
        dict1 = request.body
        dict1 = json.loads(dict1)
        print(dict1)
        name = dict1['name']
        price = dict1['price']
        book_obj = Book.objects.filter(pk=id).update(name=name, price=price)
        return JsonResponse({'code': 100, 'msg': '成功'})
	#删除一本书
    def delete(self, request, id):
        Book.objects.filter(pk=id).delete()
        return JsonResponse({'code': 100, 'msg': '成功'})

urls.py

from django.urls import path
from app01 import views
urlpatterns = [
    #    path('admin/', admin.site.urls),
    path('books/', views.BookView.as_view()),
    path('books/<int:id>/', views.BookDetailView.as_view()),

]

2 使用drf快速实现5个接口

models.py

from django.db import models
# Create your models here.

class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.IntegerField()

views.py

from .serializer import BookSerializer
from rest_framework.viewsets import ModelViewSet

class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

urls.py

from app01.views import BookView
from rest_framework.routers import SimpleRouter

router = SimpleRouter()
router.register('books', BookView, 'books')
urlpatterns += router.urls

3 APIView+序列化类+Response写5个接口

models.py

from django.db import models
# Create your models here.

class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.IntegerField()

serializer.py

from rest_framework import serializers
from .models import Book


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'

views.py

from rest_framework.views import APIView  # APIView继承了djagno原来的View
from .serializer import BookSerializer
from rest_framework.response import Response
from app01.models import Book




class BookView(APIView):
    # 查询所有
    def get(self, request):
        print('----',type(request))  #  rest_framework.request.Request
        book_list = Book.objects.all()
        # drf提供了序列化类(先别关注)
        ser = BookSerializer(instance=book_list, many=True)  # 序列化
        return Response({'code': 100, 'msg': '成功', 'result': ser.data})
	#新增一条
    def post(self, request):
        ser = BookSerializer(data=request.data)  # 反序列化
        if ser.is_valid():  # 数据校验---》有些不合法的禁止
            ser.save()  # 保存到数据库中
        return Response({'code': 100, 'msg': '成功'})





class BookDetailView(APIView):
    # 查询单条
    def get(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book, many=False)  # 序列化
        return Response({'code': 100, 'msg': '成功', 'result': ser.data})

    # 修改一条
    def put(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book, data=request.data)  # 反序列化
        if ser.is_valid():  # 数据校验---》有些不合法的禁止
            ser.save()  # 保存到数据库中
        return Response({'code': 100, 'msg': '成功'})
	# 删除一条
    def delete(self, request, pk):
        Book.objects.filter(pk=pk).delete()
        return Response({'code': 100, 'msg': '删除成功'})

urls.py

from django.urls import path
from app01 import views
urlpatterns = [
    #    path('admin/', admin.site.urls),
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>/', views.BookDetailView.as_view()),

]

标签:入门,models,request,第一节,api,https,import,序列化,drf
From: https://www.cnblogs.com/azhengya/p/17494435.html

相关文章

  • 小白必备的Less基础入门指南,教你从零开始!
    Less(LeanerStyleSheets的缩写)是一门向后兼容的 CSS 扩展语言。,它扩展了CSS(层叠样式表)的功能并提供了更灵活、更强大的样式定义和管理机制。通过使用Less,开发人员可以编写可维护、可重用的样式代码,并以简洁的语法实现复杂的样式效果。本文将介绍Less的基本概念和特性,以及......
  • AIGC:入门简介
    当提到AIGC(ArtificialIntelligenceandGeneralComputing,人工智能与通用计算)时,我们涉及到了两个重要的领域:人工智能和通用计算。本文将带您了解AIGC的基础知识,从入门到精通。第一部分:入门什么是人工智能(AI)?人工智能是一种模拟人类智慧的科学和技术。它涉及构建智能系统,使其......
  • gravitee服务网关快速入门
    下载简单说说这个网关服务吧,这是博主所理解的。gravitee采用了前后分离的设计方案:主要包括了前端页面的显示,api的转发,api的管理      转自:https://www.jianshu.com/p/c3b179693877 将下载下来的包传到服务器上,就可以开始修改配置文件了。搭建......
  • 迅为视频 | RKNPU2 从入门到实践RK3568/RK3568开发板教程
     迅为基于瑞芯微RK3568和RK3588处理器设计开发的两款开发板都自带NPU,RK3568自带1T算力的NPU、RK3588自带6T算力的NPU,且这两款开发板使用的都是RKNPU2。    (RKNPU发展历程) RKNPU2较RKNPU1有较大的提升,但市面上关于这方面的资料却寥寥无几,导致很多想学习这方面知识的小......
  • ctfshow web入门
    CTFshowweb入门命令执行web29<?php/*#-*-coding:utf-8-*-#@Author:h1xa#@Date:2020-09-0400:12:34#@LastModifiedby:h1xa#@LastModifiedtime:2020-09-0400:26:48#@email:[email protected]#@link:https://ctfer.com*/error_reporting(0......
  • iOS开发系列课程(01) --- iOS编程入门
    iOS概述什么是iOS  iOS是苹果公司为它的移动设备(iPhone、iPad、iWatch等)开发的移动操作系统。iOS发展史2007年苹果发布iPhoneRunsOSX2008年更名iPhoneOS2010年更名iOS2012年WWCD2012上发布iOS62013年WWCD2013上发布iOS72014年WWCD2014上发布iOS8和Swift2015年WWCD2015......
  • MyBatis入门指南
    MyBatis起源于iBatis,iBatis是ClintonBegin在2002年发起的开源项目,于2010年6月16日从Apache的网站退役,并被GoogleCode托管,改名为MyBatis。MyBatis是一个支持普通SQL查询、存储过程和高级映射的优秀的持久层框架,它消除了几乎所有的JDBC代码、对参数的手工设置以及对结果集繁琐的处......
  • Swift开发图解入门
    《论语·卫灵公》有一段经典对白:『子贡问为仁。子曰:工欲善其事,必先利其器。……』。对于一个程序员来说,好的工具不意味着一定能产生优质的代码,但是好的工具对提升开发效率的作用还是不言而喻的。想要用Swift做iOS开发,唯一可选的利器就是Xcode6了,童鞋们可以从下面的网站获得Xcode6的......
  • 期货是怎么交易的?从入门到精通全方面解析
    期货市场是金融市场里较为热门的投资领域之一。期货合约是购买者和卖方达成了买卖协议,在特定的时间和价格交割特定量的商品或金融资产。期货市场交易活动的复杂性和变化性使得期货市场的交易不仅需要资深的投资者,还需要有相应的知识和技能才能够深入了解和适当地投资。那么,期货是怎......
  • lazy-nvim插件管理器基础入门
    一篇通过使用lazy.nvim进行nvim插件管理的入门笔记。基础安装init.lua路径:stdpath("config")/init.luastdpath("config")macOS/Linux:~/.config/nvimWindows:~/AppData/Local/nvim--bootstraplazy.nvim--./lua/lazynvim-init.luarequire("lazynvim-init"......