drf 一

目录

1.drf简单使用
2.drf快速使用
3.CBV源码分析和APIView源码分析
4.Request对象分析
5.序列化器介绍和使用

1.drf简单使用

1 可以更方便的使用django写出符合resful规范的接口(不用也可以写符合规范的接口)
2 是一个app
3 pip3 install djangorestframework
4 https://www.django-rest-framework.org/
    
    
5 简单使用(csrf已经禁用掉了)
#路由
path('test/', views.Test.as_view()),
# 视图类
from rest_framework.views import APIView
from rest_framework.response import Response
class Test(APIView):
    def get(self,request):
        return Response({'name':'lqz','age':'19'})
    def post(self,request):
        return Response({'name': 'egon', 'age': '19'})
# 注册app
INSTALLED_APPS = [
    
    'rest_framework'
]
# 在请求地址中访问
http://127.0.0.1:8001/test/

2.drf快速使用

2.1 views.py

from rest_framework.viewsets import ModelViewSet
from app import models
from app.serializer import  BookSerializer
class BookView(ModelViewSet):
    serializer_class =BookSerializer
    queryset = models.Book.objects.all()

2.2 serializer.py

from rest_framework.serializers import ModelSerializer
from app import models
class BookSerializer(ModelSerializer):
    class Meta:
        model = models.Book
        fields = '__all__'

2.3 urls.py

from rest_framework.routers import SimpleRouter
from app import views

router = SimpleRouter()
router.register('books', views.BookView)
urlpatterns = [
    path('admin/', admin.site.urls),
]
urlpatterns += router.urls

2.4 在setting的app中配置

INSTALLED_APPS = [
    'rest_framework'
]

2.5 models.py

class Book(models.Model):
    name = models.CharField(max_length=32)
    publish = models.CharField(max_length=32)
    price = models.IntegerField()

3.CBV源码分析和APIView源码分析

    path('test/',views.TestView.as_view()),
    # path('test/',View类的as_view内部有个view闭包函数内存地址),
    '''
    1 path的第二个参数是:View类的as_view内部有个view闭包函数内存地址
    2 一旦有请求来了,匹配test路径成功
    3 执行第二个参数view函数内存地址(requset)
    4 本质执行了self.dispatch(request)
    5 通过反射去获得方法(如果是get请求,就是get方法)
     if request.method.lower() in self.http_method_names:
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    6 执行get方法,传入参数
    handler(request, *args, **kwargs)
    '''

APIView的执行流程

    # path('test/',APIView类的as_view内部是用了View的as_view内的view闭包函数),
    '''
    1 path的第二个参数是:APIView类的as_view内部是用了View的as_view内的view闭包函数
    2 一旦有请求来了,匹配test路径成功
    3 执行第二个参数view函数内存地址(requset),还是执行View的as_view内的view闭包函数,但是加了个csrf_exempt装饰器
    4 所以,继承了APIView的所有接口,都没有csrf的校验了 (*****************)
    5 执行self.dispatch(request)----》APIView类的
        def dispatch(self, request, *args, **kwargs):
            # 以后所有的request对象,都是****新的request对象***,它是drf的Request类的对象
            request = self.initialize_request(request, *args, **kwargs)
            self.request = request
            try:
                #整个drf的执行流程内的权限,频率,认证
                self.initial(request, *args, **kwargs)
                if request.method.lower() in self.http_method_names:
                    handler = getattr(self, request.method.lower(),
                                      self.http_method_not_allowed)
                else:
                    handler = self.http_method_not_allowed
    
                response = handler(request, *args, **kwargs)
    
            except Exception as exc:
                # 全局异常
                response = self.handle_exception(exc)
            # 响应
            self.response = self.finalize_response(request, response, *args, **kwargs)
            return self.response

    '''
    
### request = self.initialize_request(request, *args, **kwargs)
##返回的request对象是drf   Request类的request对象
def initialize_request(self, request, *args, **kwargs):
    return Request(
        request,
        parsers=self.get_parsers(),
        authenticators=self.get_authenticators(),
        negotiator=self.get_content_negotiator(),
        parser_context=parser_context
    )
### *******以后,在视图类中使用的request对象已经不是原来的request对象了,现在都是drf的request对象了



 #####你需要记住的
    -0 所有的csrf都不校验了
    -1 request对象变成了新的request对象,drf的request对象
    -2 执行了权限,频率,认证
    -3 捕获了全局异常(统一处理异常)
    -4 处理了response对象,如果浏览器访问是一个样,postman访问又一个样
    -5 以后,在视图类中使用的request对象已经不是原来的request对象了,现在都是drf的request对象了
  

4.Request对象分析

1 django 原生的Request:django.core.handlers.wsgi.WSGIRequest
2 drf的Request:rest_framework.request.Request

3 drf的request对象内有原生的request
    request._request:原生的Request
4 在视图类中使用
    request.method  拿到的就是请求方式,
    正常拿,应该request._request.method
5 如何实现这种操作?
    -对象.属性会触发 类的__getattr__方法
    
    
6 drf的Request类重写了__getattr__
    def __getattr__(self, attr):
        try:
            # 去原生的request反射属性
            return getattr(self._request, attr)
        except AttributeError:
            return self.__getattribute__(attr)
        
        
7 虽然视图类中request对象变成了drf的request,但是用起来,跟原来的一样,只不过它多了一些属性
    -request.data  #post请求提交的数据,不论什么格式,都在它中
    -requst.query_params# get请求提交的数据(查询参数)
    
    
8 重点记住:
    -drf的request对象用起来跟原来一样(重写了__getattr__)
    -request.data  #post请求提交的数据,不论什么格式,都在它中
    -requst.query_params# get请求提交的数据(查询参数)

5.序列化器介绍和使用

1 序列化:把python中的对象转成json格式字符串
2 反序列化:把json格式字符串转成python中的对象
3 注意:drf的序列化组件(序列化器)
    把对象(Book,queryset对象)转成字典
    因为有字典,直接丢到Response中就可以了

1 写一个序列化的类,继承Serializer
class BookSerializer(serializers.Serializer):
    # 在这里写要序列化的字段
    # 序列化字段类(有很多,常用的就几个,等同于models中的字段类)
    # 字段类,有很多字段参数()
    name = serializers.CharField()
    price = serializers.IntegerField()
    # publish = serializers.CharField()
2 在类中写要序列化的字段
    name = serializers.CharField()
    price = serializers.IntegerField()
3 在视图类中使用(实例化)
    book_list = models.Book.objects.all()                   
    book_ser=BookSerializer(instance=book_list,many=True)
4 得到序列化后的数据,返回
    book_ser.data
    
5 字段参数,source,指定要序列化表中的哪个字段

5.1 source

1 指定要序列化的字段(数据表中字段)
  publish = serializers.CharField(source='publish.city')
2 指定方法
3 深度表查询
2 用的最多:只有一个字段(也可以跨表)

5.2 SerializerMethodField

1 用的最多,跨表查(要么是列表,要么是字典)
publish=serializers.SerializerMethodField()
def get_publish(self,obj):
        return {'name':obj.publish.name,'city':obj.publish.city}

authors = serializers.SerializerMethodField()
def get_authors(self, obj):
       return [{'name':author.name, 'age': author.age} for author in obj.authors.all()]

在模型表中写方法

# 表模型中写的
def publish_name(self):
   return {'name':self.publish.name,'city':self.publish.city}

@property
def author_list(self):
   return [{'name':author.name,'age':author.age,'id':author.nid} for author in self.authors.all()]

#序列化类中
# publish = serializers.CharField(source='publish_name')
publish_name = serializers.DictField()
author_list=serializers.ListField()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,012评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,628评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,653评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,485评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,574评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,590评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,596评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,340评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,794评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,102评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,276评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,940评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,583评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,201评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,441评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,173评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,136评论 2 352

推荐阅读更多精彩内容