目录
动静分离
动:动态数据
静:静态文件
动静不分离
随着技术的发展:
-
前端技术越来越复杂,后端的学习成本变高了。
-
使用web技术终端变多了,比如:pc,小程序,移动端
动静分离(前后端分离)
Restful与接口文档
为了规范接口开发,后端工程师需要遵循RestFul风格和编写接口文档
Restful:(英文:Representational State Transfer,简称REST)是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义返回数据。
-
API与用户的通信协议,总是使用HTTPS协议。
-
在域名上和常规的页面有区分,例如:
https://www.ujiuye.com 网页地址 https://www.ujiuye.com/api/v1.0/ 接口地址
- 规范:在url上不可以出现动词
对学员信息编写接口 https://www.ujiuye.com/api/v1.0/get_student/ get就是动词,不好 GET https://www.ujiuye.com/api/v1.0/student/ get请求方式,返回所有学员信息 GET https://www.ujiuye.com/api/v1.0/student/1/ get请求方式,返回id为1的学员信息 GET https://www.ujiuye.com/api/v1.0/student/?age=12 get请求方式,返回age为12的学员信息 POST https://www.ujiuye.com/api/v1.0/student/ post请求方式,保存学员形象 PUT https://www.ujiuye.com/api/v1.0/student/1/ put请求方式,修改id为1的学员信息 DELETE https://www.ujiuye.com/api/v1.0/student/1/ delete请求方式,删除id为1的学员
- 服务器向用户返回的状态码和提示信息,常见的有以下一些(方括号中是该状态码对应的HTTP动词)。
200 OK - [GET]:服务器成功返回用户请求的数据 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 - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。 410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。 422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。 500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
- 针对不同操作,服务器向用户返回的结果应该符合以下规范。
GET /collection:返回资源对象的列表(数组) GET /collection/resource:返回单个资源对象 POST /collection:返回新生成的资源对象 PUT /collection/resource:返回完整的资源对象 DELETE /collection/resource:返回一个空文档
-
RESTful API最好做到Hypermedia(即返回结果中提供链接,连向其他API方法),使得用户不查文档,也知道下一步应该做什么。接口文档:网关:接口地址,比如:
https://www.ujiuye.com/api/v1.0/
接口描述:
支持接口的功能和效果
请求描述
请求的格式,请求需要携带的参数,参数的含义
-
参考
https://opendocs.alipay.com/apis
CORS问题
同源问题
一个源的定义:如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源。(举路由例子来说明)
同源策略:同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。注意:浏览器只会阻止ajax和form请求,不会阻止src请求
接口地址:
https://inedx.com/api/v2.9
https://helloworld.com
这样:
https://helloworld.com的网页无法请求https://inedx.com/api/v2.9的数据,需要开发者手动解除同源问题。
方法1:
使用django-cors-headers方法
- 安装cors模块:pip install django-cors-headers
- 安装应用:settings当中INSTALLED_APPS部分添加:corsheaders
- settings当中MIDDLEWARE_CLASSES添加:'corsheaders.middleware.CorsMiddleware',
- 配置白名单:CORS_ORIGIN_WHITELIST
- 后端是否支持跨域的cookie的操作:CORS_ALLOW_CREDENTIALS
- 后端允许的请求方法:CORS_ALLOW_METHODS
- 后端允许的请求头内容:CORS_ALLOW_HEADERS
方法2:
response["Access-Control-Allow-Origin"] = "http://192.168.10.101:8080"
response["Access-Control-Allow-Credentials"] = "true"
responsereutrn response["Access-Control-Allow-Methods"] = "GET,POST"
response["Access-Control-Allow-Headers"] = "Origin,Content-Type,Cookie,Accept,Token"
FBV与CBV
F function(用的很少)
FBV:函数视图,视图功能是一个函数,编写简单,但是不适合复杂的代码。
from django.http import JsonResponse
def books(request):
"""
FBV 函数视图
:param request:
:return:
"""
return JsonResponse({"code": 200,"data": []})
C class
CBV: 类视图,使用类进行视图功能的编写,比较笨重。
from django.views import View
from django.http import JsonResponse
class BookView(View):
def __init__(self,**kwargs):
super(BookView).__init__(**kwargs)
self.result = {
"code": 200,
"data": [
]
}
def get(self,request):
self.result["data"].append("get 请求")
return JsonResponse(self.result)
def post(self,request):
self.result["data"].append("post 请求")
return JsonResponse(self.result)
def put(self,request):
self.result["data"].append("put 请求")
return JsonResponse(self.result)
def delete(self,request):
self.result["data"].append("delete 请求")
return JsonResponse(self.result)
路由配置
from django.contrib import admin
from django.urls import path,re_path
from Dj.views import *
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', BookView.as_view()),
]
接口辅助工具 postman:
类视图的csrf问题:
from django.views.decorators.csrf import csrf_exempt
#csrf_exampt 避免csrf保护
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', csrf_exempt(BookView.as_view())),
# path('books/', books),
]
完整的接口代码
class BookView(View):
def __init__(self,**kwargs):
super(BookView).__init__(**kwargs)
self.result = {
"code": 200,
"data": [
]
}
def serialize_book(self,obj):
result = {
"id": obj.id,
"title": obj.title,
"author": obj.author,
"type": obj.type,
"description": obj.description,
"public_time": obj.public_time,
"picture": "http://127.0.0.1:8000" + obj.picture.url.replace("/media/","/static/")
}
return result
def get(self,request,id = 0):
"""
books/ 返回所有书籍
books/1 返回id为1的书籍
:param request:
:return:
"""
if id:
try:
book = Books.objects.get(id = id)
except Exception as e:
self.result["code"] = 400
self.result["data"].append(str(e))
else:
self.result["data"].append(
self.serialize_book(book)
)
else:
search_key = request.GET.dict()
books = Books.objects.filter(**search_key)
self.result["data"] = [self.serialize_book(i) for i in books]
return JsonResponse(self.result)
def post(self,request):
data = request.POST
author = data.get("author")
type = data.get("type")
description = data.get("description")
public_time = data.get("public_time")
picture = request.FILES.get("picture")
books = Books()
books.author = author
books.type = type
books.description = description
books.public_time = public_time
books.picture = picture
books.save()
self.result["data"].append(
self.serialize_book(books)
)
return JsonResponse(self.result)
def put(self,request,id):
"""
获取put数据
"""
data = MultiPartParser(
request.META,
request,
request.upload_handlers
).parse()[0].dict() #接收put数据
books = Books.objects.filter(id = id) #查询
books.update(**data) #更新
self.result["data"] = [self.serialize_book(i) for i in books]
return JsonResponse(self.result)
def delete(self,request,id):
try:
book = Books.objects.get(id = id)
except Exception as e:
self.result["code"] = 400
self.result["data"].append(str(e))
else:
book.delete()
return JsonResponse(self.result)
Django-RESTfulFramewrok
通常三方开发的模块都是以django App的形式出现的。
Django-restframework是进行接口快速开发的Django插件,加快了开发效率,减少了代码重构的可能
安装
pip install djangorestframework
快速开始
1. 配置settings
2. 编写序列化文件
3. 编写类视图
4. 编写路由
上述案例完成了最基本的项目功能,接下来需要了解以下内容
了解restful的三个部分
序列化:
序列化最先解决的是将ORM数据实例转换为字典类型的问题。但是在发展的过程当中发现,反序列化也很重要。
快速序列化,使用ModelSerializer,这个方法基础了基础的Serializer方法,实现了对数据模型的快速遍历。
restful反序列化实现了数据的校验
- 使用validate_字段
class BooksSerializer(serializers.Serializer): """ 完成关于项目的序列化 """ title = serializers.CharField() author = serializers.CharField() type = serializers.CharField() description = serializers.CharField() public_time = serializers.DateField() # picture = serializers.ImageField() def validate_title(self,value): #只能对对应的字段进行校验 if "坏蛋" in value: raise serializers.ValidationError("敏感词错误") return value
- 使用validate
class BooksSerializer(serializers.Serializer): """ 完成关于项目的序列化 """ title = serializers.CharField() author = serializers.CharField() type = serializers.CharField() description = serializers.CharField() public_time = serializers.DateField() # picture = serializers.ImageField() def validate(self, attrs): #可以对当前序列化的所有字段校验 print(attrs)
- 使用字段的validators属性
def title_valid(value): if "坏蛋" in value: raise serializers.ValidationError("敏感词错误") return value class BooksSerializer(serializers.Serializer): """ 完成关于项目的序列化 """ title = serializers.CharField(validators=[title_valid]) author = serializers.CharField() type = serializers.CharField() description = serializers.CharField() public_time = serializers.DateField()
视图:
在restful当中,将试图划分成了两个部分,一部分是配置部分,用来加载各种过滤器,比如分页,比如分组查询。另外的的一部分用来做具体功能的实现。掌握各种类的拼装
路由: