django_rfw_3

本篇內(nèi)容

補(bǔ)充:

關(guān)于實(shí)例化
v1 = ['view.xxx.path.Role','view.xxx.path.']

回顧

為什么用 django restframework?

關(guān)于認(rèn)證泣洞、權(quán)限、節(jié)流验辞,只需要寫類咖楣,就可以實(shí)現(xiàn)他們的方法返回值就可。
它幫我們實(shí)現(xiàn)了一些功能棍弄。

設(shè)計(jì)好的點(diǎn)?

單獨(dú)視圖配置和全局配置, 它的全局配置類似django中間件(importlib + 反射)披摄。
動(dòng)態(tài)配置可擴(kuò)展(用戶下單后,通過短信勇凭、郵件等提醒)疚膊。

關(guān)于它的原理:

基于 cbv,和 django 繼承的是同一個(gè)虾标。
請(qǐng)求進(jìn)來之后寓盗,先執(zhí)行 dispatch ( 五大功能,都是在 dispatch 里面實(shí)現(xiàn))璧函。

  • 先執(zhí)行 as_view()
  • view 函數(shù)
    obj = cls()
    傀蚌。。蘸吓。
    return self.dispatch()
  • dispatch
    • 封裝 request
    • 版本
    • 認(rèn)證 -> request.user -> 循環(huán)對(duì)象善炫,執(zhí)行_authticate
    • 權(quán)限
    • 節(jié)流

新 request對(duì)象(request,認(rèn)證相關(guān))

如果新 req 對(duì)象里面沒有你要的東西库继,就去舊的 request 里面找销部。
request.query_params
request.POST
request.Meta

今日內(nèi)容

  1. 版本摸航,
  2. 解析器,
  3. 序列化舅桩,
  4. 分頁

版本和解析器一旦配置好酱虎,基本可以不用再動(dòng)。
序列化:

  • QuuerySet 類型 -> list,dict
  • 請(qǐng)求驗(yàn)證
    django form 組件也可以用在 restframework擂涛。

1. 為什么要有版本读串?

如果是version_1,就返回111
如果是version_2撒妈,就返回22
如果是version_3恢暖,就返回3
自己可以在 url 里面寫,然后 request 獲取再判斷就可以狰右。

但是d_rfw 已經(jīng)幫你做好了杰捂。
from rest_framework.versioning
versioning_class = QueryParameterVersioning # 這個(gè)就是幫你獲取 version 的值。
推薦:
versioning_class = UrlPathVersioning

版本源碼執(zhí)行流程
1. 進(jìn)來先到 dispatch()
   def dispatch(self, request, *args, **kwargs):
2. self.initial(request, *args, **kwargs)
3.  # 處理版本信息
    # 這兩句是處理版本信息棋蚌,點(diǎn)擊self.determine_version
      version, scheme = self.determine_version(request, *args, **kwargs)
      request.version, request.versioning_scheme = version, scheme
4. def determine_version(self, request, *args, **kwargs):
       if self.versioning_class is None:
          return (None, None)
       scheme = self.versioning_class()
       return (scheme.determine_version(request, *args, **kwargs), scheme)
5. URLPathVersioning.determine_version(self, request, *args, **kwargs):
   return version
6. 封裝到 request 中
   request.version, request.versioning_scheme = version, scheme
7. 使用
   class URLPathVersion(APIView):
  # 關(guān)于 urlpath
  versioning_class = URLPathVersioning

  def get(self,request,*args,**kwargs):
      print(request.version)
      print(request.versioning_scheme)

2. 解析器

解析器對(duì)請(qǐng)求的數(shù)據(jù)解析
d_rdw 是針對(duì)請(qǐng)求頭解析嫁佳。

request.POST 不一定拿得到值,這個(gè)和 Content_Type 有關(guān)谷暮。

  • Content_Type : application/url-encoding

    • 以這個(gè)發(fā)送的話蒿往,post 和 body 里面都會(huì)有值。
    • 弊端:只有在 body 里可以拿到Bytes 類型的變態(tài)大叔湿弦。
  • d_rdw: parse_classes = [JONParse ,FormDataParse]

  • 最常用的即 JSONParse
    解析器小總結(jié):

    • 何時(shí)執(zhí)行瓤漏? 只有執(zhí)行 request.data/request.FILES/reqeust.POST
      • 根據(jù) content_type頭,判斷是否支持颊埃。
2. rest framework解析器
        請(qǐng)求的數(shù)據(jù)進(jìn)行解析:請(qǐng)求體進(jìn)行解析蔬充。表示服務(wù)端可以解析的數(shù)據(jù)格式的種類。
        
            Content-Type: application/url-encoding.....
            request.body
            request.POST
            
            Content-Type: application/json.....
            request.body
            request.POST
        
        客戶端:
            Content-Type: application/json
            '{"name":"alex","age":123}'
        
        服務(wù)端接收:
            讀取客戶端發(fā)送的Content-Type的值 application/json
            
            parser_classes = [JSONParser,]
            media_type_list = ['application/json',]
        
            如果客戶端的Content-Type的值和 application/json 匹配:JSONParser處理數(shù)據(jù)
            如果客戶端的Content-Type的值和 application/x-www-form-urlencoded 匹配:FormParser處理數(shù)據(jù)
        
        
        配置:
            單視圖:
            class UsersView(APIView):
                parser_classes = [JSONParser,]
                
            全局配置:
                REST_FRAMEWORK = {
                    'VERSION_PARAM':'version',
                    'DEFAULT_VERSION':'v1',
                    'ALLOWED_VERSIONS':['v1','v2'],
                    # 'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.HostNameVersioning"
                    'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning",
                    'DEFAULT_PARSER_CLASSES':[
                        'rest_framework.parsers.JSONParser',
                        'rest_framework.parsers.FormParser',
                    ]
                }

3. 序列化 重點(diǎn)0嗬<⒙!

這 tm 是什么肥败?
- 序列化: 對(duì)象 --> 字符串趾浅,
- 反序列化: 字符串 --> 對(duì)象。
- 目前學(xué)過的:json/pickle

restful 序列化 存在的意義:
- 就是為了解決 QuerySet 的序列化問題馒稍。

models.py

from django.db import models

# Create your models here.

class Menu(models.Model):
    name = models.CharField(max_length=32)

class Group(models.Model):
    title = models.CharField(max_length=32)
    mu = models.ForeignKey(to="Menu",default=1)

class UserInfo(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)

    group = models.ForeignKey(to='Group')
    roles = models.ManyToManyField(to='Role')


class Role(models.Model):
    name = models.CharField(max_length=32)

復(fù)雜序列化
views.py

a. 復(fù)雜序列化
解決方案一:
class MyCharField(serializers.CharField):
    def to_representation(self, value):
        data_list = []
        for row in value:
            data_list.append(row.name)
        return data_list


class UsersSerializer(serializers.Serializer):
    name = serializers.CharField()  # obj.name
    pwd = serializers.CharField()  # obj.pwd
    group_id = serializers.CharField()  # obj.group_id
    xxxx = serializers.CharField(source="group.title")  # obj.group.title
    x1 = serializers.CharField(source="group.mu.name")  # obj.mu.name
    # x2 = serializers.CharField(source="roles.all") # obj.mu.name
    x2 = MyCharField(source="roles.all")  # obj.mu.name


解決方案二:
class MyCharField(serializers.CharField):
    def to_representation(self, value):
        return {'id': value.pk, 'name': value.name}


class UsersSerializer(serializers.Serializer):
    name = serializers.CharField()  # obj.name
    pwd = serializers.CharField()  # obj.pwd
    group_id = serializers.CharField()  # obj.group_id
    xxxx = serializers.CharField(source="group.title")  # obj.group.title
    x1 = serializers.CharField(source="group.mu.name")  # obj.mu.name
    # x2 = serializers.CharField(source="roles.all") # obj.mu.name
    x2 = serializers.ListField(child=MyCharField(), source="roles.all")  # obj.mu.name


這是復(fù)雜序列化的第三種方法皿哨,也是極力推薦的方法   *************
class UserSerializer(serializers.Serializer):
    name = serializers.CharField()     # obj.name
    pwd = serializers.CharField()       # obj.pwd
    group_id = serializers.CharField()  # obj.group_id
    g_title = serializers.CharField(source='group.title')   # obj.group.title
    g_mu_name = serializers.CharField(source='group.mu.name') # obj.group.name

    # M2M,這樣寫的話纽谒,只能拿到 對(duì)象
    # roles = serializers.CharField(source='roles.all') # "roles": "<QuerySet [<Role: Role object>]>"
    roles = serializers.CharField(source='roles.all') # "roles": "<QuerySet [<Role: Role object>]>"

    xx = serializers.SerializerMethodField()
    def get_xx(self,obj):
        role_list = obj.roles.all()
        data_list = []
        for role_obj in role_list:
            data_list.append({'pk':role_obj.pk,'name':role_obj.name,})
        return data_list


不管哪種方法证膨,都走這個(gè)視圖
class UserView(APIView):
    def get(self,request,*args,**kwargs):
        self.dispatch
        # 方式一:用我們之前最簡單粗暴的方法。
        # user_list = models.UserInfo.objects.all().values('name','pwd','group_id','group__title','group__mu__name')
        # return Response(user_list)

        # 方式二:多對(duì)象
        user_list = models.UserInfo.objects.all()
        # print(user_list)
        # obj = user_list.first()
        # o_name = obj.roles.all()
        # for i in o_name:
        #     print(i.name)
        ser = UserSerializer(instance=user_list,many=True)
        return Response(ser.data)

b. 基于 model鼓黔。   在序列化里面繼承了 ModelSerializer類
class PasswordValidator(object):
    def __init__(self, base):
        self.base = base

    def __call__(self, value):
        if value != self.base:
            message = '用戶輸入的值必須是 %s.' % self.base
            raise serializers.ValidationError(message)

    def set_context(self, serializer_field):
        """
        This hook is called by the serializer instance,
        prior to the validation call being made.
        """
        # 執(zhí)行驗(yàn)證之前調(diào)用,serializer_fields是當(dāng)前字段對(duì)象
        pass

#  注意這里繼承的類:ModelSerializer
class UsersSerializer(serializers.ModelSerializer):
    x = serializers.CharField(source='name')
    class Meta:
        model = models.UserInfo
        # fields = "__all__"
        fields = ['name', 'pwd', 'x', 'group'] # 自定義字段時(shí)候要注意指定 source央勒,source里面的數(shù)據(jù)必須是數(shù)據(jù)庫有的不见。
        extra_kwargs = {
            'name': {'min_length': 6},
            'pwd': {'validators': [PasswordValidator(666), ]}}



# 使用
class UsersView(APIView):
    def get(self,request,*args,**kwargs):
        # self.dispatch
        user_list = models.UserInfo.objects.all()
        # [obj1,obj2,obj3]
        # 序列化。
        ser = UsersSerializer(instance=user_list,many=True,context={'request':request})
        return Response(ser.data)

    def post(self,request,*args,**kwargs):
        # 驗(yàn)證:對(duì)請(qǐng)求發(fā)來的數(shù)據(jù)進(jìn)行驗(yàn)證崔步。
        ser = UsersSerializer(data=request.data)
        if ser.is_valid():
            print(ser.validated_data)
        else:
            print(ser.errors)
        return Response('...')



c. 生成 url
class Users_Serializer(serializers.ModelSerializer):
    group = serializers.HyperlinkedIdentityField(view_name='detail')
    class Meta:
        model = models.UserInfo
        fields = '__all__'
        extra_kwargs = {
            'user': {'min_length': 6},
            'pwd': {'validators': [PasswordValidator(666),]}
        }

class Users_View(APIView):
    def get(self, request, *args, **kwargs):
        # 序列化稳吮,將數(shù)據(jù)庫查詢字段序列化為字典
        data_list = models.UserInfo.objects.all()
        ser = Users_Serializer(instance=data_list, many=True, context={'request': request})
        # 或
        # obj = models.UserInfo.objects.all().first()
        # ser = UserSerializer(instance=obj, many=False)
        return Response(ser.data)

    def post(self, request, *args, **kwargs):
        # 驗(yàn)證,對(duì)請(qǐng)求發(fā)來的數(shù)據(jù)進(jìn)行驗(yàn)證
        print(request.data)
        ser = Users_Serializer(data=request.data)
        if ser.is_valid():
            print(ser.validated_data)
        else:
            print(ser.errors)

        return Response('POST請(qǐng)求井濒,響應(yīng)內(nèi)容')



d. 自動(dòng)生成 url    繼承該類: HyperlinkedModelSerializer

class UsersSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"
        # fields = ['id','name','pwd']

    class UsersView(APIView):
        def get(self,request,*args,**kwargs):
            self.dispatch
            # 方式一:
            # user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")
            # return Response(user_list)

            # 方式二之多對(duì)象
            user_list = models.UserInfo.objects.all()
            # [obj1,obj2,obj3]
            ser = UsersSerializer(instance=user_list,many=True,context={'request':request})
            return Response(ser.data)



e. 關(guān)于請(qǐng)求數(shù)據(jù)驗(yàn)證
# 第一種:
class PasswordValidator(object):
    def __init__(self, base):
        self.base = base

    def __call__(self, value):
        if value != self.base:
            message = '用戶輸入的值必須是 %s.' % self.base
            raise serializers.ValidationError(message)

    def set_context(self, serializer_field):
        """
        This hook is called by the serializer instance,
        prior to the validation call being made.
        """
        # 執(zhí)行驗(yàn)證之前調(diào)用,serializer_fields是當(dāng)前字段對(duì)象
        pass


class UsersSerializer(serializers.Serializer):
    name = serializers.CharField(min_length=6)
    pwd = serializers.CharField(error_messages={'required': '密碼不能為空'}, validators=[PasswordValidator('666')])


# 第二種
class PasswordValidator(object):
    def __init__(self, base):
        self.base = base

    def __call__(self, value):
        if value != self.base:
            message = '用戶輸入的值必須是 %s.' % self.base
            raise serializers.ValidationError(message)

    def set_context(self, serializer_field):
        """
        This hook is called by the serializer instance,
        prior to the validation call being made.
        """
        # 執(zhí)行驗(yàn)證之前調(diào)用,serializer_fields是當(dāng)前字段對(duì)象
        pass


class UsersSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"
        extra_kwargs = {
            'name': {'min_length': 6},
            'pwd': {'validators': [PasswordValidator(666), ]}
        }


使用:
class UsersView(APIView):
    def get(self, request, *args, **kwargs):
        self.dispatch
        # 方式一:
        # user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")
        # return Response(user_list)

        # 方式二之多對(duì)象
        user_list = models.UserInfo.objects.all()
        # [obj1,obj2,obj3]
        ser = UsersSerializer(instance=user_list, many=True, context={'request': request})
        return Response(ser.data)

    def post(self, request, *args, **kwargs):
        ser = UsersSerializer(data=request.data)
        if ser.is_valid():
            print(ser.validated_data)
        else:
            print(ser.errors)
        return Response('...')
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末灶似,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瑞你,更是在濱河造成了極大的恐慌酪惭,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件者甲,死亡現(xiàn)場離奇詭異春感,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)虏缸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門鲫懒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人寇钉,你說我怎么就攤上這事刀疙〔芭猓” “怎么了扫倡?”我有些...
    開封第一講書人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長竟纳。 經(jīng)常有香客問我撵溃,道長,這世上最難降的妖魔是什么锥累? 我笑而不...
    開封第一講書人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任缘挑,我火速辦了婚禮,結(jié)果婚禮上桶略,老公的妹妹穿的比我還像新娘语淘。我一直安慰自己,他們只是感情好际歼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開白布惶翻。 她就那樣靜靜地躺著,像睡著了一般鹅心。 火紅的嫁衣襯著肌膚如雪吕粗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,245評(píng)論 1 299
  • 那天旭愧,我揣著相機(jī)與錄音颅筋,去河邊找鬼宙暇。 笑死,一個(gè)胖子當(dāng)著我的面吹牛议泵,可吹牛的內(nèi)容都是我干的占贫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼先口,長吁一口氣:“原來是場噩夢啊……” “哼靶剑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起池充,我...
    開封第一講書人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤桩引,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后收夸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坑匠,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年卧惜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了厘灼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡咽瓷,死狀恐怖设凹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情茅姜,我是刑警寧澤闪朱,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站钻洒,受9級(jí)特大地震影響奋姿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜素标,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一称诗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧头遭,春花似錦寓免、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至享潜,卻和暖如春困鸥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來泰國打工疾就, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留澜术,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓猬腰,卻偏偏與公主長得像鸟废,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子姑荷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理盒延,服務(wù)發(fā)現(xiàn),斷路器鼠冕,智...
    卡卡羅2017閱讀 134,654評(píng)論 18 139
  • Refer to: www.threemeal.com/blog/12/ 中間件 中間件是一個(gè)鉤子框架添寺,它們可以介...
    蘭山小亭閱讀 16,483評(píng)論 9 165
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 10,965評(píng)論 6 13
  • 一杯咖啡 被晨起的勺子攪拌 我仍困意未消,衣衫不整 旁邊飄著剛熄滅的香煙氤氳 襯著我的愁容 一粒冰糖 落杯中 依稀...
    愛風(fēng)城閱讀 401評(píng)論 2 10
  • 近日懈费,花舞人間對(duì)新津计露、眉山等地免費(fèi),趁著星期天憎乙,小游一番票罐。 早已不是杜鵑花開的時(shí)節(jié),荷花也漸漸敗了泞边,只有走馬觀花该押,...
    星星嗦閱讀 246評(píng)論 0 0