drf——第一周总结

1.什么是api接口

前后端信息交互的媒介
    前端访问路由 执行视图函数 返回json格式字符串	通过api接口实现

2.restful规范

什么是restful?
表征性状态转移
    写api接口的规范	101.使用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')
posted @   扶我上码  阅读(29)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示