## 昨日内容回顾 ### 1 web应用开发模式 ```python -前后端混合:bbs项目,图书馆里-->模板语法-->后端通过模板语法把模板进行填充【xxx.html】 -前后端分离:后端,不需要写前端,只需要提供接口;前端负责前端 -PC端,web端,网页,网站 -app:安卓,ios -小程序:微信小程序,支付宝小程序 ``` ### 2 API接口 ```python -前后端交互的媒介--前端指的是大前端,不仅仅是网站,还有app,小程序,后端:python,go,java...的后端 -url: -请求方式:get,post,put,delete,patch... -请求数据:地址栏中数据-->request.GET,请求体中数据:request.POST -响应数据:json ``` ### 3 接口测试工具--postman ```python -请求体的编码格式 -urlencode:默认情况--ke value形式--组成xxx=xx&yyy=yyy 形式放到请求中 -reuqest.body -form-data:传文件和数据,组装成很复杂形式,不能从request.body中获取 -json:放在body体中{"name":"zang","age":18} -返回数据 -body:响应体--如果是浏览器就是我们看到的页面,如果是postman就是显示的代码 -响应头 -响应Cookie ``` ## 今日内容概要 restful规范(重要,不难) 序列化与反序列化 基于django原生编写5个接口 drf介绍和快速使用 cbv源码分析 ## 今日内容详细 ### restful规范(重要,不难) 概念:REST全程Representational State Transfer,中文意思是表述:表征性状态转移,它首次出现在2000年Roy Fielding的博士论文中 RESTFUL是一种定义Web API接口的设计风格,尤其适用于前后端分离的应用模式中 ### 10个规范 #### 1 数据的安全保障,通常使用https(http+ssl/tsl)协议 url链接一般都采用https协议进行传输 采用https协议,可以提高数据交互过程中的安全性 #### 2 接口中带api标识 https://`api`.lqz.com/books https://www.lqz.com/`api`/books 我们喜欢用这个 #### 3 多版本共存,路径中带版本信息 https://api.lqz.com/`v1`/login https://www.lqz.com/api/`v2`/login #### 4 数据即是资源,均使用名词,尽量不要出现动词(最核心的) 接口一般都是完成前后台数据交互,交互的数据我们一般称之为资源 接口形式 https://api.baidu.com/`users` https://api.baidu.com/`books` 特殊的接口可以出现动词,因为这写接口一般没有一个明确的资源,或是动词就是接口的核心含义 https://api.baidu.com/`login` #### 5 资源操作由请求方式决定(method) 操作资源一般都会涉及到增删改查,我们提供请求方式来标识增删改查动作 https://api.baidu.com/books -get请求:获取所有书 https://api.baidu.com/books/1/ -get请求:获取主键为1的书 https://api.baidu.com/books -post请求:新增一本书 https://api.baidu.com/books/1/ -put请求:修改主键为1书 https://api.baidu.com/books/1/ -delete请求:删除主键为1的书 #### 6 在请求地址中带过滤条件 https://api.baidu.com/books?`name=红&price=99` #### 7 响应状态码:两套 http响应状态码:在向响应头中 1xx:请求正在处理 2xx:成功响应 3xx:重定向 301永久重定向302临时重定向 4xx:客户端错误 404没找到资源 403权限问题 5xx:服务端错误 具体响应状态码可以看这里:https://blog.csdn.net/li_chunlong/article/details/120787872 公司内部规定的响应状态码,放在响应体中 {"code":0} 我们一般使用100 101 102这种 #### 8 返回数据中带错误信息 {"code":0,"msg":"ok/用户名错误"} #### 9 返回的结果应该符合以下规范--好多公司不遵循这个 GET 获取所有数据:返回资源对象的列表(数组):[{name:红楼梦,price:99},{name:红楼梦,price:99},{name:红楼梦,price:99}] GET 单个对象:返回单个资源对象:{name:红楼梦,price:99} POST 新增对象:返回新生成的资源对象:{name:西游记,price:99} PUT 修改对象:返回完整的资源对象:{name:西游记,price:100} DELETE 删除:返回一个空文档:` ` #### 10 响应数据中带链接 ```python { "status":0, "message":"ok", "result_type":"poi_type", "results":[ { "name":"肯德基(堡镇店)", "location":{ "lat":31.544448, "lng":121.63229 }, "address":"上海市崇明区石岛路617弄11号12号", "province":"上海市", "city":"上海市", "area":"崇明区", "detail":1, "uid":"213d741cd24ba80ee8e58280" "img":"www.baidu.com/avatar.img" #响应数据中带有链接 }]} ``` ### 序列化与反序列化 api接口开发,最核心最常见的一个过程就是序列化,所谓序列化就是【数据之间转换格式】,序列化可以分为两个阶段: #### 序列化:把我们识别的数据转换成指定格式提供给别人 字典,列表---json格式存到文件中 例如:django中获取的数据默认是模型对象,但是模型对象数据无法直接提供给前端或别的平台使用,所以我们需要把数据进行序列化,变成字符串或者json数据,提供给别人 `read`过程 #### 反序列化:把别人提供的数据转换/还原成我们需要的格式 例如:前端js提供的json数据,对于python而言就是字符串,我们需要进行反序列化换成模型类对象,这样我们才能把数据保存到数据库中 `write`过程 ### 基于django原生编写5个接口 #### 以后写的接口,基本上都是5个接口及其变形 查所有 get 查询单个 get 新增一个 post 修改一个 put/patch 删除一个 delete #### 基于books单表为例,写5个接口 创建book表 表迁移 录入假数据:直接录入,后台管理录 写查询所有接口--遵循restful规范,使用cbv 新增一个数据 查询一个 修改一个:put提交的数据,不能requests.POST中取 删除一个 views.py ```python from django.shortcuts import render, HttpResponse from django.http import JsonResponse # Create your views here. from django.views import View from .models import Book from django.core import serializers import json class BookView(View): """图书视图类""" def get(self, request): books = Book.objects.all() # return JsonResponse(serializers.serialize('json',books),json_dumps_params={'ensure_ascii':False},safe=False) book_list = [] for book in books: book_list.append({'id': book.pk, 'name': book.name, 'price': book.price, 'publish': book.publish}) return JsonResponse(book_list, safe=False, json_dumps_params={'ensure_ascii': False}) def post(self, request): print(request.POST) print(request.body) name = request.POST.get('name') price = request.POST.get('price') publish = request.POST.get('publish') book = Book.objects.create(name=name, price=price, publish=publish) return JsonResponse({'id': book.pk, 'name': book.name, 'price': book.price, 'publish': book.publish}) class BookViewParms(View): def get(self, request, pk): book = Book.objects.filter(pk=pk).first() return JsonResponse({'id': book.pk, 'name': book.name, 'price': book.price, 'publish': book.publish}) def put(self, request, pk): print(request.POST) print(request.body) book = Book.objects.filter(pk=pk) book.update(**json.loads(request.body)) # 局部修改 book.name=name先删除后增加 book = book.first() return JsonResponse({'id': book.pk, 'name': book.name, 'price': book.price, 'publish': book.publish}) def delete(self, request, pk): Book.objects.filter(pk=pk).delete() return HttpResponse('') ``` urls.py ```python from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('api/v1/books/', views.BookView.as_view()), path('api/v1/books/', views.BookViewParms.as_view()), ] ``` models.py ```python from django.db import models # Create your models here. class Book(models.Model): name = models.CharField(max_length=32, verbose_name='书名') price = models.CharField(max_length=32, verbose_name='价格') publish = models.CharField(max_length=32, verbose_name='出版社') class Meta: verbose_name_plural = '图书表' def __str__(self): return f'图书表对象:{self.name}' ```  put请求方式form-data携带参数  urlencode携带  raw源方式为json格式字符串  ### drf介绍和快速使用 djangorestframework: drf 帮助我们快速的实现符合restful规范的接口 django最新4.x 一般都会用最新版的上一般3.x drf最新支持到django 3.x 最新不支持django2.x 安装drf `pip install djangorestframework` 如果django是老版本的话,会自动把你的django更新到最新版django4.x  如果不想使用django最新版可以在自己手动自动版本安装回来 `pip install django==2.2.2`  #### 使用drf编写5个接口 使用drf编写的接口三种携带数据编码方式都可以使用,原生的有的请求对于某些支持的不好需要我们自己手动做一些调整 models.py ```python from django.db import models # Create your models here. class Book(models.Model): name = models.CharField(max_length=32, verbose_name='书名', null=True, blank=True) price = models.CharField(max_length=32, verbose_name='价格', null=True, blank=True) publish = models.CharField(max_length=32, verbose_name='出版社', null=True, blank=True) class Meta: verbose_name_plural = '书籍表' def __str__(self): return f'书籍表对象{self.name}' ``` views.py ```python from django.shortcuts import render from rest_framework.viewsets import ModelViewSet from .models import Book from .serializer import BookSerializer # Create your views here. class BookView(ModelViewSet): queryset = Book.objects.all() serializer_class = BookSerializer ``` serializer.py ```python from rest_framework import serializers from .models import Book class BookSerializer(serializers.ModelSerializer): class Meta: model = Book fields = '__all__' ``` urls.py ```python from django.contrib import admin from django.urls import path from app01 import views from rest_framework.routers import SimpleRouter router = SimpleRouter() router.register('api/v1/books', views.BookView, 'books') urlpatterns = [ path('admin/', admin.site.urls), ] urlpatterns += router.urls ``` settings.py ```python INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', 'rest_framework' #别忘了注册rest——framework app ] ```     ### CBV源码分析 ```python # 1 路由中写的:path('api/v1/books/', views.BookView.as_view()),第二个参数无论是fbv还是cbv放的都是函数内存地址 -当请求来了,匹配成功会执行,views.BookView.as_view()(request) -views.BookView.as_view()执行结果是View的类方法as_view返回的结果是内层函数view,是个函数内层地址 -本身请求来了,匹配成功,会执行view(request) def view(request, *args, **kwargs): return self.dispatch(request, *args, **kwargs) -self.dispatch View类的方法 def dispatch(self, request, *args, **kwargs): # request.method请求方式转成小写,必须在列表中才能往下走 if request.method.lower() in self.http_method_names: # 反射,去self【视图类的对象:BookView】,去通过get字符串,反射出属性或方法 # BookView的get方法 handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed # BookView的get方法,加括号,传入request return handler(request, *args, **kwargs) ``` Last modification:February 9th, 2023 at 10:22 pm © 允许规范转载 Support 如果觉得我的文章对你有用,请随意赞赏 ×Close Appreciate the author Sweeping payments
Comment here is closed