drf框架
一:drfdrf的全称: django rest framework 用处: 用来前后端分离的项目: 结合前段的vue框架,数据库mysql 二: 安装在命令行中输入: pip3 install djangorestframework 三: 配置INSTALLED_APPS = [ ‘app01.apps.App01Config‘,# App的注册,一般命名:api # 注册: 在setting中配置,rest_framework实质上是一个app,需要注册才可以使用 # 但是我不注册,照样能使用 ‘rest_framework‘,] 四: 接口1)? 什么是接口? 大白话解释: 两个东西通过一个东西进行连接、通信等, 一个东西就叫做接口 wed程序中的接口:连接前后台页面尽心数据交互的媒介 2) restful规范: 为什么要有restful规范: 因为后台的语言有多种,这样接口就会有多种,所以要统一规范 1. api表示url接口, 2. 使用https协议,数据更加安全 3. 一个接口有多个版本,需要在url连接中表示,v1表示版本 如: api. xiaohuar.com/v1/... 4. 接口操作的数据源称之为资源,资源在url连接中一般采用复数 如: api. xiaohuar.com/books/... 5. 请求的方式有多种,用一个url处理,为了保证不混乱,通过请求方式标识操作资源的方式 get(pk)? ? ? ? ?获取所有(获取一个) post? ? ? ? ? ? ?增加一个或多个 delete? ? ? ? ? 删除一个或多个(数据不会真正的删除,只会用一个字段标识) put/patch? ? ?整体更新/局部更新 6. 资源往往涉及数据的各种操作:? ? 过滤,排序,限制 如:? api.xiaohuar.com/book/?search=西&ordering=-price&limit=3 查找书本中有西的,价格从小到大,找出三本 7. 返回状态码:? 前台和后台约定好的 { "status": 0 # 操作资源成功 "msg": "登录成功" # 文字提示信息 "results": 需要返回前段的数据 } {"status": 1} # 操作资源失败 {"status": 2} # 操作资源成功,但是没有与之匹配的数据 8. 不能直接还回的资源,如视频,图片,等, 需要还回url连接 五: 基于restful的原生路由总路由:? from django.urls import url,include from contrib importadmin urlpatterns = [ url(r‘^admin‘/,admin.site.urls),url(r‘^api/‘,include(‘api.urls‘)) ] 子路由: from django.urls import url urlpatterns = [ url(r‘^book/$‘,views.Book.as_view()),# 查看有的数据 models.py from django.db.models import F # 快熟导入模块alt + enter键 class BaseModel(models.Model): is_delete = models.BooleanField(default=False) create_time = models.DateTimeField(auto_now_add=True) class Meta: abstract = True # 其它模型类继承该类,该类不创建表 class Book(BaseModel): name = models.CharField(max_length=64) price = models.DecimalField(max_digits=6,decimal_places=2) img = models.ImageField(upload_to=‘icon‘,default=‘icon/default.jpg‘) publish = models.ForeignKey( to=‘Publish‘,db_constraint=False,related_name=‘books‘,on_delete=models.DO_NOTHING ) authors = models.ManyToManyField( to=‘Author‘,related_name=‘books‘ ) @property def publish_name(self): return self.publish.name @property def author_list(self): return self.authors.values(‘name‘,‘age‘,mobile = F(‘detail__mobile‘)).all() class Meta: db_table = ‘book‘ verbose_name_plural = ‘书籍‘ def __str__(self): return self.name class Publish(BaseModel): name = models.CharField(max_length=64) address = models.CharField(max_length=64) class Meta: db_table = ‘publish‘ verbose_name_plural = ‘出版社‘ def __str__(self): return self.name class Author(BaseModel): name = models.CharField(max_length=32) age = models.IntegerField() class Meta: db_table = ‘author‘ verbose_name_plural = ‘作者‘ def __str__(self): return self.name class AuthorDetail(BaseModel): mobile = models.CharField(max_length=11) # 外键字段建在作者详情中: 因为不经常被查询,建在作者那是被经常查,走数据库 author = models.OneToOneField( # 和那张表建立连接,也可以不写 to=‘Author‘,# 与连接的表断开连接 db_constraint=False,# 通过detail进行连表查询 related_name= ‘detail‘,# 正向按字段,反向查询按detail # 级联 on_delete= models.CASCADE,# on_delete= models.DO_NOTHING, # null=True, # on_delete=models.SET_NULL, # default= 0, # on_delete=models.SET_DEFAULT ) class Meta: db_table = ‘author_detail‘ verbose_name_plural = ‘作者详情‘ def __str__(self): return ‘%s的详情‘ % self.author.name ? 数据库迁移命令: python manage.py makemigrations # 数据库迁移记录 python manage.py migrate # 创建数据库 # 创建管理有用户,对创建的表进行操作 createsuperman admin.py from django.contrib import admin from . import models # Register your models here. # admin.site.register(models.Books) # admin.site.register(models.User) # 只有在admin.py中注册之后,才能在浏览器的admin的身份尽心操作 admin.site.register(models.Book) admin.site.register(models.Author) admin.site.register(models.Publish) admin.site.register(models.AuthorDetail) views.py from rest_framework.views import APIView from . import models from rest_framework.response import Response from . import serializers class Book(APIView): # 单查 全查 def get(self,request,*args,**kwargs): pk = kwargs.get(‘pk‘) # 单查 if pk: try: # 查找没有被删除的书籍 is_delete = False book_obj = models.Book.objects.get(pk=pk,is_delete=False) book_ser = serializers.BookModelSerializer(book_obj) except: return Response({ ‘status‘: 1,‘msg‘: ‘数据不存在‘ }) # 群查 else: # 查找没有被删除的书籍 is_delete = False book_obj = models.Book.objects.filter(is_delete=False).all() book_ser = serializers.BookModelSerializer(book_obj,many=True) return Response({ ‘status‘: 0,‘msg‘: ‘ok‘,‘results‘: book_ser.data }) # 单增 群增 def post(self,**kwargs): # 前台出过来的数据在request.data里面 request_data = request.data # 单增 if isinstance(request_data,dict): many = False # 群增 elif isinstance(request_data,list): many = True # 发送的数据格式不对 else: return Response({ ‘status‘: 1,‘msg‘: ‘传入的数据有误,只能传{},or [{},{}]‘ }) # 数据交给序列化校验 # 点data查看many book_ser = serializers.BookModelSerializer(data=request_data,many=many) # 当校验失败,raise_exception=True马上终止当前视图方法,报异常返回给前台 book_ser.is_valid(raise_exception=True) # 校验成功保存数据 book_obj = book_ser.save() return Response({ ‘status‘: 0,‘msg‘: ‘OK‘,‘results‘: serializers.BookModelSerializer(book_obj,many=many).data }) # 单删 群删 def delete(self,**kwargs): # print(kwargs.get(‘pk‘),66666666666666) # print(request.data.get(‘pks‘),7777777777) pk = kwargs.get(‘pk‘) # 一个pk走的是在url路径中拼接 if pk: pks = [pk] else: pks = request.data.get(‘pks‘) # 多个pk的数据在request.data中 # 只能删除一次,不是真正意义上的删除,只是把is_delete=True,所以用的是update方法 if models.Book.objects.filter(pk__in=pks,is_delete=False).update(is_delete=True): return Response({ ‘status‘: 0,‘msg‘: ‘ok‘ }) return Response({ ‘status‘: 1,‘msg0‘: ‘已经被删除过‘ }) 六: postman接口工具安装: 官网直接下载,点击安装即可 1) get请求: 携带参数采用Params 数据在request.query_params中 2) post请求:? 提交数据的三种方式: form_data,urlencode,json 数据在request.data中 注意: 所有的请求都可以携带请求头 七: drf的请求生命周期1)? 路由匹配走APIView的as_view函数 2)? 在as_view函数中调用父类的as_view(原生django的as_view),增加了禁用csrf认证 3)? 在父类的as_view中dispatch方法请求走的是APIView的dispatch 5)? 完成任务方法交给视图类处理,得到请求的响应结果,返回给前台 八: 视图家族1.? views.py 视图>>APIView: 主要是设置1).??drf提供的渲染类,?解析模块规定数据的格式(form_data,urlencoded,json),异常模块的配置 REST_FRAMEWORK = { # drf提供的渲染类 ‘DEFAULT_RENDERER_CLASSES‘: [ ‘rest_framework.renderers.JSONRenderer‘,‘rest_framework.renderers.BrowsableAPIRenderer‘,],# 解析模块 数据格式 # as_view>dispatch>self.initialize_request>self.get_parsers()>parser_classes ‘DEFAULT_PARSER_CLASSES‘: [ ‘rest_framework.parsers.JSONParser‘,‘rest_framework.parsers.FormParser‘,‘rest_framework.parsers.MultiPartParser‘ ],# 全局配置异常模块 ‘EXCEPTION_HANDLER‘: ‘app01.exception.exception_handler‘,} 2) urls.py urlpatterns = [ # 不能缺少book/ "/",在postman中的路径必须有"/" url(r‘^v1/books/$‘,url(r‘^v1/books/(?P<pk>.*)/$‘,] 3) views.py from rest_framework.views import APIView
2. generics.py工具视图>> GenericAPIView1)? 完全继承APIView 2) 继承之后的操作 get_queryset(): 从类属性queryset中获取model的queryset数据 get_object(): 从类属性queryset中获取model的queryset数据,在通过有名分组pk确定唯一对象 get_serializer(): 从类属性serializer_class中获取的serializer的序列化类 3) urls.py urlpatterns = [ url(r‘^v2/books/$‘,views.BooKGenericAPIView.as_view()),url(r‘^v2/books/(?P<pk>.*)/$‘,] 4) views.py ? from rest_framework.generics import GenericAPIView from . import serializers from . import models from utils.response import APIResponse # 见名知导入的文件 class BooKGenericAPIView(GenericAPIView): queryset = models.Book.objects.filter(is_delete=False) serializer_class = serializers.BookModelSerializer # 自定义有名分组的名字 lookup_field = ‘pk‘ # 默认 # 群取 def get(self,**kwargs): book_query = self.get_queryset() book_ser = self.get_serializer(book_query,many=True) book_data = book_ser.data return APIResponse(results=book_data) # 单增 # def get(self,**kwargs): # book_obj = self.get_object() # book_ser = self.get_serializer(book_obj) # book_data = book_ser.data # return APIResponse(results=book_data) ? 3. mixins.py1) mixins视图工具集 """ mixins视图工具集: 用来辅助GenericAPIView 1) mixins有五个工具类文件,一共提供了五个工具类,六个工具方法: 单增,单删,群查,单查,单整体改,单局部改 2) 继承工具类可以简化请求函数的实现体,但是必须继承GenericAPIView,需要GenericAPIView类提供的几个类属性和方法 3) 工具类的工具方法返回值都是Response类型对象,如果要格式化数据,返回给前台,可以通过request.data 拿到工具方法返回的Response类型的响应数据 """ 2) urls.py urlpatterns = [ url(r‘^v3/books/$‘,views.BookMixinsGenericAPIView.as_view()),url(r‘^v3/books/(?P<pk>.*)/$‘,] 3) views.py from rest_framework.mixins import ListModelMixin,RetrieveModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin from . import serializers from . import models from utils.response import APIResponse class BookMixinsGenericAPIView(GenericAPIView,ListModelMixin,DestroyModelMixin): queryset = models.Book.objects.filter(is_delete=False) serializer_class = serializers.BookModelSerializer lookup_field = ‘pk‘ # 坑: TypeError: Object of type ‘Response‘ is not JSON serializable # 解决: response.data def get(self,**kwargs): # 单查,群查 if "pk" in kwargs: response = self.retrieve(request,**kwargs) else: response = self.list(request,**kwargs) return APIResponse(results=response.data) def post(self,**kwargs): response = self.create(request,**kwargs) return APIResponse(results=response.data) def put(self,**kwargs): response = self.update(request,**kwargs) return APIResponse(results=response.data) def patch(self,**kwargs): response = self.partial_update(request,**kwargs) return APIResponse(results=response.data) 4. viewsets.py视图集1)?? 2) urls.py urlpatterns = [ url(r‘^v6/books/$‘,views.BookModelViewSet.as_view({‘get‘: ‘list‘,‘post‘: ‘create‘})),# post 单增 url(r‘^v6/books/(?P<pk>.*)/$‘,views.BookModelViewSet.as_view({ ‘get‘: ‘retrieve‘,‘put‘: ‘update‘,‘patch‘: ‘partial_update‘,‘delete‘: ‘destroy‘ })),] 3) views.py from rest_framework.viewsets import ModelViewSet class BookModelViewSet(ModelViewSet): queryset = models.Book.objects.filter(is_delete=False) serializer_class = serializers.BookModelSerializer def destroy(self,**kwargs): instance = self.get_object() # type models.Book对象 # 传入的参数不对 if not instance: return APIResponse(1,‘删除失败‘) # 实际操作在此之前就完成了 instance.is_delete = True instance.save() return APIResponse(0,‘删除成功‘) """ 群增,群删,群局部改,群整体改???????????""" (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |