DRF框架


1、RESTful規范

  1.1 REST風格:表屬性狀態轉移

    1.1.1資源:在web中凡是有被引用的必要的都叫資源

    1.1.2 URI:統一資源標識符    URI包含URL 

    1.1.3 URL:統一資源定位符

    1.1.4 統一資源接口,不再像以前django項目中url中增刪改查都分別對應一個url,而是url中只寫一個名詞最為代表性的

        路由,比如(只寫book,不需要book_list,book_append,book_edit,book_delate),其他的功能根據HTTP請求方式

        的不同來對資源進行操作。

    1.1.5 前后端傳遞的是資源的表述

    1.1.6 前端展示的是資源的狀態

    1.1.7 通過超鏈接的指引來告訴用戶接下來有哪些資源狀態可以進入

  1.2 核心思想:

    1.2.1 面向對象去編程,url中盡量用名詞,不要用動詞

    1.2.2 根據HTTP請求方式的不同對資源進行不同的操作。

  1.3 url中要體現的信息

    1.3.1 版本

    1.3.2 API

    1.3.3 過濾條件

    1.3.4 HTTPS

  1.4 返回的要求

    1.4.1 要攜帶狀態嗎

    1.4.2 返回值

        get 獲取的是所有或者單挑數據

        post 返回的是新增的這條數據

        put/patch 返回的是更新的數據

        delete 返回空

    1.4.3 攜帶錯誤信息

    1.4.4 攜帶超鏈接

2、FBV 和 CBV 的區別

    def dispatch(self, request, *args, **kwargs):
    # GET POST
    # BookView().get
    # DJango的View只做了CBV的分發
    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
    return handler(request, *args, **kwargs)

3、下載DRF

    pip istall djangorestframwork

    在settings的APP項中注冊rest_framwork

4、APIView 和View的區別

  4.1、APIView繼承了View

  4.2、重寫了as_view方法,豁免了csrf 

  4.3、重新封裝了request

      新的request變成了Request的實例化對象,

        request = self.initialize_request(request, *args, **kwargs)
        self.request = request

      舊的request 變成了_request

        self._request = 舊的request  

        def query_params(self):
          return self._request.GET
        def data(self):
          return post請求的數據

5、序列化

  5.1 django實現序列化

    5.1.1 通過.values 獲取到QuerySet對象 ,通過JsonResponse進行序列化。JsonResponse和HttpResponse的區別是能

      夠處理date/datetime類型的數據,但都不能解決外鍵關系的序列化

    5.1.2 django的序列化器 serializes.seialize 能夠序列化queryset,但是也不能解決外間關系的序列化

  5.2 DRF的序列化組件

    5.2.1 先聲明一個序列化器,類比django中的model.py文件

    5.2.2 在視圖中使用序列化器序列化queryset

    5.2.3 序列化好的數據在set_obj.data中

  5.3 對於GET請求

    5.3.1 先獲取Book對象的所有信息

       book_queryset = Book.objects.all()

    5.3.2 ser_obj = BookSerializer(book_queryset,many=True) 

      如果有many=True 認為我們的queryset是一個可迭代對象,循環我們的queryset拿到每一個模型對象

      把每個模型對象的字段跟序列化器的字段進行匹配,匹配成功的進行序列化,沒有匹配成功的丟棄,

      但是序列化器里的字段必須在要匹配的字段中

  5.4 對於POST請求

    5.4.1 注意序列化和反序列化不統一的字段

        id = serializers.IntegerField(required=False)      required=False表示之序列化,不進行校驗

        read_only = True :表示只進行正向序列化

        write_only = True:表示只進行反向序列化

    5.4.2 視圖中      

    def post(self, request):
        book_obj = request.data                     # data是post提交的數據
        ser_obj = BookSerializer(data=book_obj)
        print(type(ser_obj), ser_obj)
        if ser_obj.is_valid():
            ser_obj.save()                          # 此save不同於ORM操作中的save,此save只是單純的調用了create方法,所以要去重寫create方法,其實是create方法對數據進行了保存
            return Response(ser_obj.validated_data)
        return Response(ser_obj.errors)

 

    5.4.3 重寫create方法

def create(self, validated_data):
         book_obj = Book.objects.create(title=validated_data['title'],
                                        publisher_time=validated_data['publisher_time'],
                                        category=validated_data['post_category'],
                                        publisher_id=validated_data['publisher_id'],
                                        )
         book_obj.authors.add(*validated_data['author_list'])
         return book_obj

   5.5對於PUT/PATCH請求

    5.5.1在視圖中

    def put(self, request, id):
        book_obj = Book.objects.filter(id=id).first()
        ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True)
        if ser_obj.is_valid():
            ser_obj.save()                                 # 在put中,save()的時候需要重寫update方法     
            return Response(ser_obj.validated_data)
        return Response(ser_obj.errors)

    5.5.2重寫的update

    def update(self, instance, validated_data):
        # instance 更新的book_obj 對象
        # validated_data 校驗通過的數據
        # ORM做更新操作
        instance.title = validated_data.get("title", instance.title)        #字典.get取值的時候即使沒有也不會報錯
        instance.pub_time = validated_data.get("pub_time", instance.pub_time)
        instance.category = validated_data.get("post_category", instance.category)
        instance.publisher_id = validated_data.get("publisher_id", instance.publisher_id)
        if validated_data.get("author_list"):
            instance.authors.set(validated_data["author_list"])
        instance.save()
        return instance

  6.1驗證

    6.1.1局部鈎子函數

    def validate_title(self, value):           # 局部鈎子需要傳value作為參數
        print(2222)
        # value就是title的值 對value處理
        if "python" not in value.lower():
            raise serializers.ValidationError("標題必須含有python")
        return value

    6.1.2全局鈎子函數

    def validate(self, attrs):        # 全局鈎子,需要傳參數attrs 
        print(33333)
        # attrs 字典有你傳過來的所有的字段
        print(attrs)
        if "python" in attrs["title"].lower() or attrs["post_category"] == 1:
            return attrs
        else:
            raise serializers.ValidationError("分類或標題不合符要求")

    6.1.3自定義驗證函數

def my_validate(value):                 # 自定義的函數,沒有self,把value作為參數
    print(1111)
    if "敏感信息" in value.lower():
        raise serializers.ValidationError("有敏感詞匯")
    return value
# 對於自定義的函數,需要在序列化器中的字段中加入validators=[my_validate,]
# title = serializers.CharField(max_length=32, validators=[my_validate,])

    6.1.4 驗證的鈎子函數,優先級分別是    自定義 > 局部鈎子 > 全局鈎子

    6.1.5 普通序列化器處理正反序列化的方法

  

from rest_framework import serializers
from DRF_Demo.models import Book, Publisher
from rest_framework.response import Response


class PublisherSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    name = serializers.CharField(max_length=32)


class AuthorSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    name = serializers.CharField(max_length=32)


class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField(required=False)  # required=False 只序列化不校驗
    title = serializers.CharField(max_length=32)
    publisher_time = serializers.DateField()
    category = serializers.CharField(source='get_category_display', read_only=True)

    publisher = PublisherSerializer(read_only=True)
    authors = AuthorSerializer(many=True, read_only=True)
    post_category = serializers.IntegerField(write_only=True)          # 對於反序列化的字段名稱匹配的時候,要和提交的數據的字段相同
    publisher_id = serializers.IntegerField(write_only=True)
    author_list = serializers.ListField(write_only=True)

    def create(self, validated_data):
        book_obj = Book.objects.create(title=validated_data['title'],
                                       publisher_time=validated_data['publisher_time'],
                                       category=validated_data['post_category'],
                                       publisher_id=validated_data['publisher_id'],
                                       )
        book_obj.authors.add(*validated_data['author_list'])
        return book_obj

    def update(self, instance, validated_data):
        instance.title = validated_data.get("title", instance.title)
        instance.save()
        return instance

 

  7.1 ModelSerializer

    7.1.1 類似於Django中的modelform,用於生成關聯的模型里的所有字段   

       model=表名
       fields="__all__"/["字段名",]
       exclude=["字段名",]
       depth=1 外鍵關系找一層 會讓外鍵關系字段變成read_only=True
       extra_kwargs={"字段名": {配置的屬性}}      # 對於不想要正序或者反序的字段,就用extra_kwargs={'字段名':屬性}}

    7.1.2 SerlizerMethodField() 對於重寫的正向序列化的字段,用這個方法字段來定義

    7.1.2 示例,用ModelSerilizer方法進行正反序列化,包括校驗字段

class BookSerializer(serializers.ModelSerializer):
    # SerializerMethodField是個方法字段,需要用get_publisher_info 來定義方法
    publisher_info = serializers.SerializerMethodField(read_only=True)
    authors_info = serializers.SerializerMethodField(read_only=True)

    # 通過get_變量名制定方法,obj是Book對象
    def get_publisher_info(self, obj):
        publisher_obj = obj.publisher
        # return 回來的結果返回給publisher_info,然后渲染到頁面上
        return {"id": publisher_obj.id, "name": publisher_obj.name}

    def get_authors_info(self, obj):
        authors_obj = obj.authors.all()
        return [{'id': author.id, 'name': author.name} for author in authors_obj]

    class Meta:
        model = Book
        fields = '__all__'
        # depth = 1  # depth 寫幾就是外鍵向下找幾層,一般不要超過四層。並且會讓所有外鍵變成read_only=True
        # extra_kwargs 是一個字典,處理序列化的字段,如果正向序列化不想要展現publisher 和authors字段,就將他設置成write_only=True
        extra_kwargs = {'publisher': {"write_only": True}, 'authors': {"write_only": True}}
        # 定義一個局部鈎子函數,validate_字段名,校驗title,參數要傳一個value
    def validate_title(self, value):
        if 'python' not in value.lower():
            raise serializers.ValidationError('標題必須含有python')
        return value
    def validate(self,attrs):
        if 'python' in attrs["title"].lower() or attrs["authors_info.id"] == 1:
            return attrs
        else:
            raise serializers.ValidationError('分類或標題不符合要求')

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM