drf——第一周总结
目录
1.什么是api接口
前后端信息交互的媒介
前端访问路由 执行视图函数 返回json格式字符串 通过api接口实现
2.restful规范
什么是restful?
表征性状态转移
写api接口的规范 10条
1.使用https进行数据交互
2.接口地址带api标识
3.地址带版本标识
4.地址不要有动词 复数形式
5.资源操作有请求方式决定
6.响应状态码
7.响应中带错误信息
8.响应带链接地址
9.返回的数据带具体格式
10.地址可带搜索条件
3.什么是drf
django rest_framework
一个app 需要注册 可快速生成符合restful规范的接口 只能在django框架上使用
4.CBV源码分析
path('books/', views.BookView.as_view())
先执行as_view 返回view 成了BookView.view
路由匹配成功 执行view(request) 返回dispatch()
执行dispatch()
里面一个反射关系
一个列表存了'get', 'post', 'put', 'delete'...
if request.method.lower() in 列表:
handler = getattr(self, request.method.lower())
反射取得对应的方法
return handler()
好比是执行POST请求 拿小写的post去写的视图类里找post方法
5.APIView的使用
APIView继承View 写drf就继承APIView
使用APIView执行as_view()
执行的是APIView的as_view()
view是调用的父类 还是原来的view
然后return csrf_exempt(view)
多加了一层装饰器去除csrf校验
dispatch()源码分析
包装了新的request对象 drf的Request的对象
执行视图函数之前进行了三大认证
处理了全局异常
包装了响应对象
Request对象源码分析
原本的request为现在的request._request
数据从request.data里取
请求地址中的数据从request.query_params里取
跟原来一样用
6.序列化类Serializer
序列化:后端-->前端
把数据模型对象(query_set, book)转成字典的形式 再通过Response转成json格式传给前端
反序列化:前端-->后端
1 把前端传的json格式字符串经过request.data以后变成字典
通过序列化器将字典转成模型存到数据库 ser.save()保存
2 数据校验
序列化类写法:
class BookSerializer(serializers.Serializer):
name = serializer.CharField() # 括号里写的话就是对反序列化数据的校验
price = serializer.CharField()
7.不使用drf写5接口
class BookView(View):
def get(self, request):
list = []
books = Book.objects.all()
for book in books:
list.append({'name': book.name, 'price': book.price})
return JsonResponse(list, safe=False, json_dumps_params={'ensure_ascii':False})
def post(self, request):
name = request.POST.get('name')
price = request.POST.get('price')
Book.objects.create(name=name, price=price)
return JsonResponse({'name': name, 'price': price})
class BookDetailView(View):
def get(self, request, pk):
book = Book.objects.filter(pk=pk).first()
return JsonResponse({'name': book.name, 'price': book.price})
def delete(self, request, pk):
Book.objects.filter(pk=pk).delete()
return JsonResponse({'code': 100, 'msg': '删除成功'})
def put(self, request, pk):
name = request.POST.get('name')
price = request.POST.get('price')
book = Book.objects.filter(pk=pk).update(name=name, price=price)
return JsonResponse({'code': 100, 'msg': '修改成功'})
8.使用drf的APIView写5接口
就数据从request.data里取
9.使用APIView+序列化类+Response写5接口
class BookView(APIView):
def get(request):
books = Book.objects.all()
ser = BookSerializer(instance=books, many=True)
return Response(ser.data)
def post(request):
ser = BookSerializer(data=reqeust.data)
if ser.is_vaild():
ser.save() # 保存前提 :序列化类里重写了create方法
return Response(ser.data)
else:
return Response({'code': 101, 'msg': '创建失败'})
class BookDetailView(APIView):
def get(request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book)
return Response(ser.data)
def delete(request, pk):
Book.objects.filter(pk=pk).delete()
return Response({'code': 100, 'msg': '删除成功'})
def put(request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book, data=request.data)
if ser.is_vaild():
ser.save() # 保存前提:序列化类里重写了update方法
return Response(ser.data)
else:
return Response({'code': 101, 'msg': '修改失败', 'errors': ser.errors})
# 序列化类
class BookSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True) # 只读
name = serializers.CharField(max_length=32)
price = serializers.IntegerField()
# 重写create和update
def create(self, validated_data):
book = Book.objects.create(**validated_data)
return book
def update(self, instance, validated_data):
book = Book.objects.filter(pk=pk).first()
for i,j in validated_data.items:
book.i = j
return instance
10.钩子
执行ser.is_avild()就会触发校验
第一层 name = serializers.CharField(max_length=32)
第二层 局部钩子
def validate_name(self, name):
if name.startswith('sb'):
raise ValidationError('不能以sb开头')
else:
return name
第三层 全局钩子
def validate(self, attrs):
attrs为经过一二层校验的数据
name = attrs.get('name')
price = attrs.get('price')
if name == str(price):
raise ValidationError('名字和价格不能一样')
else:
return attrs
11.序列化类ModelSerializer
用了ModelSerializer 表与字段就有对应关系
不需要重写create和update方法
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
或者
fields = ['name', 'price'] 只序列化和反序列化列表内的字段
此时反序列化默认走的model里的规则
想要增加反序列化校验规则?
# 方式1 往extra_kwargs字典里新增k(字段名)v(字典套校验属性及值)
extra_kwargs = {
'name': {'max_length': 8, 'min_length': 2},
'price': {'max_value': 10000}
}
# 方式2 重写字段 这里缩进不是在class Meta里 同级
name = serializers.CharField(max_length=8, min_length=2)
12.多表序列化
序列化类的两种写法
class BookSerializer(serializers.Serializer):
class Meta:
model = Book
fields = ['name', 'price', 'authors', 'publish']
# 写法一 重写字段 + 方法 方法返回啥 字段就是啥 该字段只能序列化
publish是关联字段 在表里会产生一个publish_id字段 只存对应的id
authors是多对多的关联字段
publish = serializers.SerializerMethodField()
def get_publish(self, obj):
# obj为当前的Book对象
return {'name': obj.publish.name, 'city': obj.publish.addr}
authors = serializers.SerializerMethodField()
def get_authors(self, obj):
author_list = []
for author in obj.authors.all():
author_list.append({'name': author.name, 'age': author.age, 'addr': author.author_detail.addr}) # 对象.的方式跨表查询
# 写法二:在models中写方法 在序列化类中写到fields中
models.py
class Book(mdoels.Model):
...
def publish_detail(self):
return {'name': self.publish.name, 'addr': self.publish.addr}
def author_list(self):
author_list = []
for author in self.auhtors.all():
author_list.append({'name': author.name, 'age': author.age, 'addr': author.authro_detail.addr})
return author_list
'写好方法后将方法添加到fields列表里'
class BookSerializer(serializers.Serializer):
class Meta:
model = Book
fields = ['name', 'price', 'authors', 'publish','author_list', 'publish_detail']
"""
相当于录入是要靠authors和publish
展示靠author_list和publish_detail
"""
# 需要字段限制
extra_kwargs = {
'publish': {'write_only': True},
'authors': {'write_only': True},
'publish_detail': {'read_only': True},
'author_list': {'read_only': True},
}
也可以重写字段的方式
publish_detail = serializers.SerializerMethodField(read_only=True)
author_list = serializers.SerializerMethodField(read_only=True)
"""
对于展示的字段publish_detail和author_list 写入后数据校验用不到自动忽略
"""
13.请求与响应
django的请求对象:request
响应对象:HttpResponse\redirect\render\JsonResponse
drf 请求对象是新的request 是drf中Request类的对象
'属性方法'
request.data
request.query_params
reqeust.FILES
响应对象是Response
'属性和方法'
data=None # 要序列化的数据 字典、列表、字符串
status=None # http响应状态码
headers=None # 响应头 一个字典
------------
template_name=None # 模板名 浏览器看到的界面
content_type=None # 默认json格式 前后端分离项目 彼此互传靠json格式
14.django国际化
三个设置
zh-hans
Asia/Shanghai
USE_TZ = False
15.models级联删除相关
publish = models.ForeignKey(to='Publish', to_field='nid', on_delete=models.CASCADE)
on_delete属性的值
models.CASCADE # 级联删除
models.SET_NULL # 设为空 前提 相关的字段null=True
models.SET_DEFAULT # 设为默认 前提 default=某个值
models.DO_NOTHING
models.SET(值,函数内存地址) # 设为某个值或余小宁某个函数
16.推演过程
2个视图基类
APIView GenericAPIView
GenericAPIView继承APIView
GenericAPIView两个属性
queryset
serializer_class
5个视图拓展类
ListModelMixin
CreateModelMixin
RetrieveModelMixin
UpdateModelMixin
DestroyModelMixin
没有继承父类
9个视图子类
CreateAPIView\ListAPIView\ListCreateAPIView
RetrieveAPIView\UpdateAPIView\DestroyAPIView
RetrieveDestoryAPIView\RetrieveUpdateAPIView\RetrieveUpdateDestroyAPIView
视图集
ViewSetMixin # 改变路由写法
ViewSet # ViewSetMixin + APIView
GenericViewSet # ViewSetMixin + GenericAPIView
ModelViewSet # 5个视图拓展类+GenericViewSet
ReadOnlyModelViewSet # RetrieveModelMixin + ListModelMixin +GenericViewSet
路由组件
自动生成路由两种写法:
# 写法1
path('books/', views.BookView.as_view({'get': 'list', 'post': 'create'}))
# 写法2
1.导入路由类
from rest_framework.routers import SimpleRouter, DefaultRouter
2.实例化对象
SimpleRouter()
或
DefaultRouter()
# 区别 DefaultRouter会给每个注册的视图类生成一个根路由
3.注册路由
router.register('books', views.BookView, 'books')
4.在总路由中注册
urlpatterns += router.urls
或
path('', include(router.urls))
action装饰器
from rest_frameword.decorators import action
class Publish(ViewSetMixin, APIView):
"""
含义:
访问了 http://127.0.0.1/publish/ycj的get或post请求都会执行imycj方法
"""
@action(method=['get', 'post'], detail=False, url_path='ycj', url_name='ycj')
def imycj(self, request):
return Response('imycj')
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?