DRF三 ------ 序列化

DRF普通序列化(瞭解一下就行)

重新創建一個新的應用

python manage.py startapp app02

創建完應用之後,要記得註冊應用
在這裏插入圖片描述

先創建模型類

from django.db import models

# Create your models here.
class Article(models.Model):
    title = models.CharField(verbose_name='標題', max_length=100)
    vum = models.IntegerField(verbose_name='瀏覽量')
    content = models.TextField(verbose_name='內容')

然後再序列化

先在app02下創建一個序列化文件serializers.py
在drf中,每一個模型都可以序列化

from rest_framework import serializers
#導入最開始的序列化
from .models import Article
#導入模型類

class ArticleSerializer(serializers.Serializer):
    #在最普通的序列化裏面,要序列化的字段、還有下面的兩個方法都需要手打出來,得自己寫
    id = serializers.IntegerField(read_only=True)
    vum = serializers.IntegerField()
    content = serializers.CharField(max_length=1000)
    title = serializers.CharField(required=True, max_length=100)

    def create(self, validated_data):
        return Article.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.title = validated_data.get('title', instance.title)
        #instance.title就是說,沒有取到的話,就用原來的數據
        instance.vum = validated_data.get('vum', instance.vum)
        instance.content = validated_data.get('content', instance.content)
        instance.save()
        #創建序列化器對象的時候,如果沒有傳遞instance實例,則調用save()方法的時候,create()被調用,
        # 相反,如果傳遞了instance實例,則調用save()方法的時候,update()被調用。
        return instance

之後就開始遷移文件,生成表

python manage.py makemigrations
python manage.py migrate

普通序列化裏面的參數約束

read_only:True表示不允許用戶自己上傳,只能用於api的輸出。
write_only: 與read_only對應
required: 顧名思義,就是這個字段是否必填。
allow_null/allow_blank:是否允許爲NULL/空 。

error_messages:出錯時,前端的信息提示。
name = serializers.CharField(required=True, min_length=6,
error_messages={
‘min_length’: ‘名字不能小於6個字符’,
‘required’: ‘請填寫名字’})

label: 字段顯示設置,如 label=’驗證碼’
help_text: 在指定字段增加一些提示文字,這兩個字段作用於api頁面比較有用

style: 說明字段的類型,這樣看可能比較抽象,看下面例子:
#在api頁面,輸入密碼就會以*顯示
password = serializers.CharField(
style={‘input_type’: ‘password’})
#會顯示選項框
color_channel = serializers.ChoiceField(
choices=[‘red’, ‘green’, ‘blue’],
style={‘base_template’: ‘radio.html’})

validators:自定義驗證邏輯

用終端傳數據

可以在pycharm自帶的數據庫裏面傳數據,也可以在終端傳入數據
這裏採用終端傳入數據

python manage.py shell 打開終端
from app02.serializers import ArticleSerializer  導入模型類
from rest_framework.renderers import JSONRenderer  可以生成json數據的包

然後開始創建數據(也就是反序列化)
反序列化的關鍵字是data

d = {"title":"這是一個測試標籤","vum":11,"content":"哈哈哈哈"}
ser = ArticleSerializer(data=d)
ser.is_valid()# 驗證數據是否正確,傳的時候如果少一個字段,會返回false
ser.save()# 保存數據

然後這個時候去看數據庫的時候(pycharm自帶的),會發現有數據
在這裏插入圖片描述

查數據

有了數據之後,就在終端接着查數據

from app02.models import *
# 查多個數據(多個對象序列化)
arts = Article.objects.all()
ser = ArticleSerializer(instace=arts,many=True)  #  如果多個對象序列化 需要加many
ser.data

在這裏插入圖片描述
這就是查到的數據,如何返回json數據呢

from rest_framework.renderers import JSONRenderer
json_data = JSONRenderer().render(ser.data)
json_data

這個json_data就是序列化好的json數據
在這裏插入圖片描述
查詢所有的數據返回的是一個列表,然後通過https response 返回就可以了
這個就是把模型轉化成json數據
這個查多個數據,也就是序列化多個數據,那單個數據可以查到嗎?

單個對象的序列化
art = Article.objects.get(id=1)
ser = ArticleSerializer(art)
json_data = JSONRenderer().render(ser.data)
json_data 

查詢當個數據返回的是字典
在這裏插入圖片描述
當我們序列化的時候,也就是查數據的時候,要用instance傳參
當我們反序列化,也就是傳入數據的時候,要用data傳參

DRF模型序列化(繼承ModelSerializer)

ModelSerializers默認幫我們實現了創建和更新方法,簡化了我們的操作,當然如果你想自己寫,可以重寫它。其餘使用方法跟普通的序列化一樣。

class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = ('id', 'title', 'vnum', 'content')       #三者取一
       #exclude = () 表示不返回字段        三者取一
       #fields = '__all__': 表示所有字段       三者取一

       #read_only_fields = () #設置只讀字段 不接受用戶修改

模型類

模型類還是和普通序列化一樣,我們用同一個例子來對比一下,普通序列化和模型序列化的區別

from django.db import models

# Create your models here.
class Article(models.Model):
    title = models.CharField(verbose_name='標題', max_length=100)
    vum = models.IntegerField(verbose_name='瀏覽量')
    content = models.TextField(verbose_name='內容')

序列化

接着在已經創建好的serializers.py上寫

from rest_framework import serializers
#導入最開始的序列化
from .models import Article
#導入模型類

#模型序列化
class ArticleSerializer(serializers.ModelSerializer):
   class Meta:
       model = Article
       fields = '__all__'
       #序列化這個模型類裏面的而全部字段

視圖(增加數據的視圖)

from django.shortcuts import render
from .models import *
#導入模型
from .serializers import *
#導入序列化類
from rest_framework.renderers import JSONRenderer
#轉json數據
from django.http import HttpResponse
from rest_framework.parsers import JSONParser
#把json數據轉成python裏的數據
from django.views.decorators.csrf import csrf_exempt
#解決403錯誤,使用這個封裝函數,把django裏面的驗證先去掉

# Create your views here.

@csrf_exempt
def article_list(request):
    if request.method == 'GET':
        #獲取數據  #查詢所有的數據
        arts = Article.objects.all()

        ser = ArticleSerializer(instance=arts,many=True)
        #序列化

        json_data = JSONRenderer().render(ser.data)
        #反序列化,轉json數據

        return HttpResponse(json_data,content_type='application/json',status=200)
    elif request.method == 'POST':
        #接收數據,把用戶輸入的json數據轉成python數據
        data = JSONParser().parse(request)#把前端傳過來的json數據轉化成python裏面的數據
        ser = ArticleSerializer(data=data)
        if ser.is_valid():
            ser.save()
            json_data = JSONRenderer().render(ser.data)
            return HttpResponse(json_data, content_type='application/json', status=201)
            #201表示創建成功數據

        json_data = JSONRenderer().render(ser.errors)
        return HttpResponse(json_data, content_type='application/json', status=400)
        #400表示get request

路由


from django.contrib import admin
from django.urls import path
from app02 import views
#導入試圖




urlpatterns = [
    path('articles/', views.article_list,name='article_list'),

]

根及路由

from django.contrib import admin
from django.urls import path,include
from app01 import views
from rest_framework.routers import DefaultRouter
#使用提供的路由


route = DefaultRouter()
#把視圖生成的路由註冊到這個裏
route.register(r'students',views.StudentViewSet)
route.register(r'groups',views.GroupViewSet)
#這樣的話,他會幫我們生成對應的路由

'''
http://127.0.0.1:8000/students就會生成這樣的路由
如果是獲取當個學生的話,路由就是
http://127.0.0.1:8000/students/1/
'''

urlpatterns = [
    path('admin/', admin.site.urls),
    # path('api/',include(route.urls)),
    # #這個加上api之後的路由就是http://127.0.0.1:8000/api/students
    path('api/',include('app02.urls'))


]

可以通過postman看一下
這是獲取數據和添加數據,還有刪除和更新

更新刪除視圖

class JSONResponse(HttpResponse):
    def __init__(self, data, **kwargs):
        content = JSONRenderer().render(data)
        kwargs['content_type'] = 'application/json'
        super(JSONResponse, self).__init__(content, **kwargs)
        #封裝一個函數
@csrf_exempt
def article_detail(request,pk):
    #要獲取單個數據,一定要傳進來一個關於這個數據的唯一標識
       try:
            art = Article.objects.get(pk=pk)
            #查詢像刪除的數據,獲取id
       except Article.DoesNotExist:
           #捕獲異常,如果這個數據不存在
           return HttpResponse(status=404)

       if request.method == 'GET':
           serializer = ArticleSerializer(instance=art)
           #把查到數據序列化
           return JSONResponse(serializer.data,status=200)

       elif request.method == 'PUT':
           data = JSONParser().parse(request)
           #解析前端的數據
           serializer = ArticleSerializer(instance=art,data=data)
           #序列化單個數據
           if serializer.is_valid():
               #如果序列化好的數據存在的話
               serializer.save()
               #就保存起來
               return JSONResponse(serializer.data,status=201)
                #返回json數據
           return JSONResponse(serializer.errors, status=400)
            #不存在的話,就返回一個error錯誤

       elif request.method == 'PATCH':
           #表示局部更新
           data = JSONParser().parse(request)
           #解析前端的數據
           serializer = ArticleSerializer(instance=art,data=data,partial=True)
           #序列化單個數據,局部更新一定要加上partial=True,默認是false
           if serializer.is_valid():
               #如果序列化好的數據存在的話
               serializer.save()
               #就保存起來
               return JSONResponse(serializer.data,status=201)
                #返回json數據
           return JSONResponse(serializer.errors, status=400)
            #不存在的話,就返回一個error錯誤
       elif request.method == 'DELETE':
           art.delete()
           #表示把查到的數據刪除
           return HttpResponse(status=204)
       #204表示刪除成功

drf模型序列化高級一

模型類

from django.db import models

# Create your models here.

class Category(models.Model):
    name = models.CharField(verbose_name='分類名字',max_length=10)




class Article(models.Model):
    title = models.CharField(verbose_name='標題', max_length=100)
    vum = models.IntegerField(verbose_name='瀏覽量')
    content = models.TextField(verbose_name='內容')
    category = models.ForeignKey(to=Category,on_delete=models.CASCADE,related_name='articles')

之後,開始遷移

python manage.py makemigrations
python manage.py migrate

序列化

from rest_framework import serializers
#導入最開始的序列化
from .models import Article,Category
#導入模型類


#模型序列化

class ArticleSerializer(serializers.ModelSerializer):
   class Meta:
       model = Article
       fields = '__all__'
       #序列化這個模型類裏面的而全部字段


class CatrgorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = ('id','name','articles')
        #因爲模型中有反向查找

視圖


from django.shortcuts import render
from .models import *
from .serializers import ArticleSerializer,CatrgorySerializer
from rest_framework.renderers import JSONRenderer
from django.http import JsonResponse,HttpResponse
from rest_framework.parsers import JSONParser
from django.http import Http404
from django.views.decorators.csrf import csrf_exempt
# Create your views here.

class JSONResponse(HttpResponse):
    def __init__(self, data, **kwargs):
        content = JSONRenderer().render(data)
        kwargs['content_type'] = 'application/json'
        super(JSONResponse, self).__init__(content, **kwargs)
        #封裝一個函數


@csrf_exempt
def article_list(request):
    if request.method == 'GET':
        #請求數據,這個過程就是要把數據序列化
        arts = Article.objects.all()
        #查詢數據
        ser = ArticleSerializer(instance=arts,many=True)
        #序列化查詢出來的數據,instance表示你要序列化的數據,
        # data表示你要反序列化的數據
        #many=True 如果你序列化的字段很多,一定要加上這個
        json_data = JSONRenderer().render(ser.data)
        #調用data方法,把序列化好的數據取出來,
        return HttpResponse(json_data,content_type='applications/json',status=200)
        #注意不要忘記,告訴瀏覽器,返回的數據類型,
        #content_type='applications/json'表示,網頁上用json形式把josn_data數據展示出來
        #狀態碼200200是響應正常的意思


    elif request.method == 'POST':
        #新增,也就是json數據轉化爲可傳輸數據
        data = JSONParser().parse(request)
        #把前端json的數據解析出來,解析成python裏面的數據類型
        serialize = ArticleSerializer(data=data)
        #反序列化數據,注意,有顏色的這個data是關鍵字
        if serialize.is_valid():
            #校驗數據,假如存在
            serialize.save()
            #就保存數據
            json_data = JSONRenderer().render(serialize.data)
            #然後再取出來數據,用json數據返回去
            return HttpResponse(json_data, content_type='applications/json', status=200)
            #201表示創建成功
        json_data = JSONRenderer().render(serialize.errors)
        #表示序列化沒有成功
        return HttpResponse(json_data, content_type='applications/json', status=400)
        #校驗不成功,就返回401未經授權






@csrf_exempt
def article_detail(request,pk):
    #要獲取單個數據,一定要傳進來一個關於這個數據的唯一標識
       try:
            art = Article.objects.get(pk=pk)
            #查詢像刪除的數據,獲取id
       except Article.DoesNotExist:
           #捕獲異常,如果這個數據不存在
           return HttpResponse(status=404)

       if request.method == 'GET':
           serializer = ArticleSerializer(instance=art)
           #把查到數據序列化
           return JSONResponse(serializer.data,status=200)

       elif request.method == 'PUT':
           data = JSONParser().parse(request)
           #解析前端的數據
           serializer = ArticleSerializer(instance=art,data=data)
           #序列化單個數據
           if serializer.is_valid():
               #如果序列化好的數據存在的話
               serializer.save()
               #就保存起來
               return JSONResponse(serializer.data,status=201)
                #返回json數據
           return JSONResponse(serializer.errors, status=400)
            #不存在的話,就返回一個error錯誤

       elif request.method == 'PATCH':
           #表示局部更新
           data = JSONParser().parse(request)
           #解析前端的數據
           serializer = ArticleSerializer(instance=art,data=data,partial=True)
           #序列化單個數據,局部更新一定要加上partial=True,默認是false
           if serializer.is_valid():
               #如果序列化好的數據存在的話
               serializer.save()
               #就保存起來
               return JSONResponse(serializer.data,status=201)
                #返回json數據
           return JSONResponse(serializer.errors, status=400)
            #不存在的話,就返回一個error錯誤
       elif request.method == 'DELETE':
           art.delete()
           #表示把查到的數據刪除
           return HttpResponse(status=204)
       #204表示刪除成功




@csrf_exempt
def category_list(request):
    if request.method == 'GET':
        #請求數據,這個過程就是要把數據序列化
        cat = Category.objects.all()
        #查詢數據
        ser = CatrgorySerializer(instance=cat,many=True)
        #序列化查詢出來的數據,instance表示你要序列化的數據,
        # data表示你要反序列化的數據
        #many=True 如果你序列化的字段很多,一定要加上這個
        json_data = JSONRenderer().render(ser.data)
        #調用data方法,把序列化好的數據取出來,
        return HttpResponse(json_data,content_type='applications/json',status=200)
        #注意不要忘記,告訴瀏覽器,返回的數據類型,
        #content_type='applications/json'表示,網頁上用json形式把josn_data數據展示出來
        #狀態碼200200是響應正常的意思


    elif request.method == 'POST':
        #新增,也就是json數據轉化爲可傳輸數據
        data = JSONParser().parse(request)
        #把前端json的數據解析出來,解析成python裏面的數據類型
        serialize = CatrgorySerializer(data=data)
        #反序列化數據,注意,有顏色的這個data是關鍵字
        if serialize.is_valid():
            #校驗數據,假如存在
            serialize.save()
            #就保存數據
            json_data = JSONRenderer().render(serialize.data)
            #然後再取出來數據,用json數據返回去
            return HttpResponse(json_data, content_type='applications/json', status=200)
            #201表示創建成功
        json_data = JSONRenderer().render(serialize.errors)
        #表示序列化沒有成功
        return HttpResponse(json_data, content_type='applications/json', status=400)
        #校驗不成功,就返回401未經授權






@csrf_exempt
def category_detail(request,pk):
    #要獲取單個數據,一定要傳進來一個關於這個數據的唯一標識
       try:
            art = Category.objects.get(pk=pk)
            #查詢像刪除的數據,獲取id
       except Category.DoesNotExist:
           #捕獲異常,如果這個數據不存在
           return HttpResponse(status=404)

       if request.method == 'GET':
           serializer = CatrgorySerializer(instance=art)
           #把查到數據序列化
           return JSONResponse(serializer.data,status=200)

       elif request.method == 'PUT':
           data = JSONParser().parse(request)
           #解析前端的數據
           serializer = CatrgorySerializer(instance=art,data=data)
           #序列化單個數據
           if serializer.is_valid():
               #如果序列化好的數據存在的話
               serializer.save()
               #就保存起來
               return JSONResponse(serializer.data)
                #返回json數據
           return JSONResponse(serializer.errors, status=400)
            #不存在的話,就返回一個error錯誤

       elif request.method == 'PATCH':
           #表示局部更新
           data = JSONParser().parse(request)
           #解析前端的數據
           serializer = CatrgorySerializer(instance=art,data=data,partial=True)
           #序列化單個數據,局部更新一定要加上partial=True,默認是false
           if serializer.is_valid():
               #如果序列化好的數據存在的話
               serializer.save()
               #就保存起來
               return JSONResponse(serializer.data)
                #返回json數據
           return JSONResponse(serializer.errors, status=400)
            #不存在的話,就返回一個error錯誤
       elif request.method == 'DELETE':
           art.delete()
           #表示把查到的數據刪除
           return HttpResponse(status=204)
       #204表示刪除成功

路由


from django.contrib import admin
from django.urls import path,include
from app02 import views


urlpatterns = [
    path('article',views.article_list,name='article-list'),
    path('articles/<int:pk>',views.article_detail,name='article-detail'),
    #這個表示獲取單個數據,一定要注意和視圖裏面的參數保持一致,主鍵要一致
    #name表示重命名
    path('category', views.category_list, name='category_list'),
    path('category/<int:pk>', views.category_detail, name='category_detail'),
]

然後就可以去訪問一下

DRF高級序列二(基於序列化)

StringRelatedField(和模型類的str配合使用,返回名字)

StringRelatedField 將返回一個對應關係 model 的 unicode() 方法的字符串。


#模型序列化
class ArticleSerializer(serializers.ModelSerializer):
   class Meta:
       category = serializers.StringRelatedField()
       model = Article
       fields = '__all__'
       #序列化這個模型類裏面的而全部字段

class Category(models.Model):
    name = models.CharField(verbose_name='分類名字',max_length=10)
    def __str__(self):
        return self.name 
        #這塊寫什麼返回什麼,寫self.name返回的是輸入的名字
        #比如寫哈哈,那麼返回的就是哈哈

在這裏插入圖片描述

 category = serializers.StringRelatedField(many=True)
 #如果是一查多的話,要寫上many=True

在這裏插入圖片描述
在Article的模型下面加上srt方法
然後去訪問標籤頁
在這裏插入圖片描述
顯示的就是對應的文章標題,而不是id

PrimaryKeyRelatedField(顯示對應模型的id)

使用 PrimaryKeyRelatedField 將返回一個對應關係 model 的主鍵。

參數:

  • queryset 用於在驗證字段輸入時模型實例查找。 關係必須明確設置 queryset,或設置 read_only = True
    many 如果是對應多個的關係,就設置爲 True
  • allow_null 如果設置爲 True,則該字段將接受 None 的值或爲空的關係的空字符串。默認爲 False
    pk_field 設置爲一個字段以控制主鍵值的序列化/反序列化。例如,pk_field = UUIDField(format =‘hex’) 將UUID主鍵序列化爲緊湊的十六進制表示。
class CategorySerializer(serializers.ModelSerializer):
    articles = serializers.PrimaryKeyRelatedField(many=True, read_only=True)

    class Meta:
        model = Category
        fields = '__all__'

PrimaryKeyRelatedField,如果是單個不需要加,many=True
在這裏插入圖片描述
標籤所對應的文章的id就會被返回,但是,其實它默認的就是返回的id

HyperlinkedRelatedField(在關聯的模型中返回超鏈接)

使用 HyperlinkedRelatedField 將返回一個超鏈接(點擊跳轉對應頁面),該鏈接指向對應關係 model 的詳細數據,view-name 是必選參數,爲對應的視圖生成超鏈接。

參數:

  • view_name 用作關係目標的視圖名稱。如果使用的是標準路由器類,那麼它的格式爲 -detail 的字符串
  • queryset 驗證字段輸入時用於模型實例查詢的查詢器。關係必須明確設置 queryset,或設置 read_only = True
  • many 如果應用於多對多關係,則應將此參數設置爲 True
  • allow_null 如果設置爲 True,則該字段將接受 None 的值或爲空的關係的空字符串。默認爲 False
  • lookup_field 應該用於查找的目標上的字段。應該對應於引用視圖上的 URL 關鍵字參數。默認值爲 pk
  • lookup_url_kwarg 與查找字段對應的 URL conf 中定義的關鍵字參數的名稱。默認使用與 lookup_field 相同的值
  • format 如果使用 format 後綴,超鏈接字段將對目標使用相同的 format 後綴,除非使用 format 參數進行覆蓋。
class CategorySerializer(serializers.ModelSerializer):
    articles = serializers.HyperlinkedRelatedField(
        many=True,#標籤查文章有很多,所以要加上這個參數,一對一的話,不用加
        read_only=True,
        view_name='article_detail',  #如果根及路由有別名的話,這個地方應該寫成 根及路由的別名:應用及路由的別名
        lookup_field='id',  # 數據庫字段的名字
        lookup_url_kwarg="id"  # 路由中參數的名字,必須和路由參數保持一致
    )

    class Meta:
        model = Category
        fields = '__all_

要想使用這個連接,必須在視圖裏面增加上下文,否則報錯。

在視圖裏面加上上下文
content={‘request’:request}
添加位置在每一個序列化的地方
在這裏插入圖片描述
就在這些地方添加

這個時候在去訪問

在這裏插入圖片描述

SlugRelatedField(可以返回對應模型的任何一個字段)

使用 SlugRelatedField 將返回一個指定對應關係 model 中的字段,需要參數 slug_field 中指定字段名稱。可以返回模型類中的任何字段

參數:

  • slug_field 應該用於表示目標的字段。這應該是唯一標識任何給定實例的字段。例如 username 。這是必選參數
  • queryset 驗證字段輸入時用於模型實例查詢的查詢器。 關係必須明確設置 queryset,或設置 read_only = True
  • many 如果應用於多對多關係,則應將此參數設置爲 True
  • allow_null 如果設置爲 True,則該字段將接受 None 的值或爲空的關係的空字符串。默認爲 False
class CategorySerializer(serializers.ModelSerializer):
    articles = serializers.SlugRelatedField(
        many=True,
        read_only=True,
        slug_field='vum'
        #這個寫什麼,就返回對應模型的值
    )

    class Meta:
        model = Category
        fields = '__all__'

在這裏插入圖片描述

HyperlinkedIdentityField(返回對應模型 視圖的超鏈接)

使用 HyperlinkedIdentityField 將返回指定 view-name 的超鏈接的字段。

參數:

  • view_name 應該用作關係目標的視圖名稱。如果您使用的是標準路由器類,則它將是格式<model_name>-detail的字符串。必選參數
  • lookup_field 應該用於查找的目標上的字段。應該對應於引用視圖上的 URL 關鍵字參數。默認值爲 pk
  • lookup_url_kwarg 與查找字段對應的 URL conf 中定義的關鍵字參數的名稱。默認使用與 lookup_field 相同的值
  • format 如果使用 format 後綴,超鏈接字段將對目標使用相同的 format 後綴,除非使用 format 參數進行覆蓋
class ArticleSerializer(serializers.ModelSerializer):
    category = serializers.HyperlinkedIdentityField(view_name="app03:category-detail", lookup_field='id')
    #view_name的格式   根及路由的別名:應用及的路由別名
    #lookup_field應用及的路由參數,保持一致

    class Meta:
        model = Article
        fields = '__all__'

-------------------------------------------------
        
class CategorySerializer(serializers.ModelSerializer):
    articles = serializers.HyperlinkedIdentityField(view_name="app03:article-detail", lookup_field='id', many=True)

    class Meta:
        model = Category
        fields = '__all__'

在這裏插入圖片描述

HyperlinkedModelSerializer(返回超鏈接)

HyperlinkedModelSerializer 類與 ModelSerializer 類相似,只不過它使用超鏈接來表示關係而不是主鍵。
view_name的參數使用方法和上面一樣

class ArticleSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Article
        fields = '__all__'

        extra_kwargs = {
            'url': {'view_name': 'app04:article-detail', 'lookup_field': 'id'},
            'category': {'view_name': 'app04:category-detail', 'lookup_field': 'pk','lookup_url_kwarg':'id'},
        }


        
class CategorySerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Category
        fields = ('id', 'name', 'articles','url')
#不寫all的原因,Category裏面沒有article字段,但是在文章的模型中用到了反向查找,就可以這麼用
        extra_kwargs = {
            'url': {'view_name': 'app04:category-detail', 'lookup_field': 'id'},
            'articles': {'view_name': 'app04:article-detail', 'lookup_field': 'id'},
        }
        
        
'''

使用extra_kwargs額外參數爲ModelSerializer添加或修改原有的選項參數---字典格式

extra_kwargs = {

			'vnum': {'min_value': 0, 'required': True},
}

'''  

extra_kwargs 裏面的寫什麼,什麼就會返回超鏈接
在這裏插入圖片描述

嵌套序列化關係模型(常用)


class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = '__all__'


class CategorySerializer(serializers.ModelSerializer):
    articles = ArticleSerializer(many=True)
#如果返回的單個的話,不需要加many = true
    class Meta:
        model = Category
        fields = '__all__'

在這裏插入圖片描述

depth

這個字段可以用來深度遍歷

#注意是ModelSerializer
class CategorySerializer(serializers.ModelSerializer):
    articles = ArticleSerializer(many=True)

    class Meta:
        model = Category
        fields = '__all__'
        depth = 2

在這裏插入圖片描述
把相關的數據找出來,depth爲幾就找幾層,一般建議2-3即可。

SerializerMethodField(自定義對應模型的屬性)

我們可以自定義一些屬性。
比如我們想看每個分類下有多少篇文章


class CategorySerializer(serializers.ModelSerializer):
    articles = ArticleSerializer(many=True)
    count = serializers.SerializerMethodField()
    #這個是自定義屬性,有了SerializerMethodField,必須實現下方的函數,那個函數也有規律

    class Meta:
        model = Category
        fields = ('id','name','articles','count')

    def get_count(self, obj):
    #函數的名字是  get_加上上面自定義的屬性名字
    #obj表示當前分類的對象
        return obj.articles.count()

在這裏插入圖片描述

source

class ArticleSerializer(serializers.ModelSerializer):
    category = serializers.CharField(source='category.id')

    class Meta:
        model = Article
        fields = '__all__'

source=‘category.id’,上面這個指定的返回id,他返回的就是id
在這裏插入圖片描述

#這個類可以定義屬性,以及想返回的值
class MyCharField(serializers.CharField):
#下面使用了這個類之後,所查到的數據都會給value,因爲查找的是所有的值,所以返回的是一個列表
#所以可以定義一個空列表,進行遍歷
    def to_representation(self, value):
        data_list = []
        for row in value:
            data_list.append({'title': row.title, 'content': row.content})
        return data_list




class CategorySerializer(serializers.ModelSerializer):
    #arts = MyCharField(source='articles.all')
    #arts = serializers.CharField(source='articles_set.all')
    #如果在模型中沒有反向查找的話,也就可以這麼寫
  
	arts = MyCharField(source='articles_set.all')
	#使用上面定義的類,然後會把查到的所有文章,都給上面的參數value,因爲是所有的文章,所以返回的是一個列表
	
    class Meta:
        model = Category
        fields = ('id', 'name', 'arts')

在這裏插入圖片描述
利用source實現可讀可寫

from collections import OrderedDict


class ChoiceDisplayField(serializers.Field):
    """Custom ChoiceField serializer field."""

    def __init__(self, choices, **kwargs):
        """init."""
        self._choices = OrderedDict(choices)
        super(ChoiceDisplayField, self).__init__(**kwargs)

    # 返回可讀性良好的字符串而不是 1,-1 這樣的數字
    def to_representation(self, obj):
        """Used while retrieving value for the field."""
        return self._choices[obj]

    def to_internal_value(self, data):
        """Used while storing value for the field."""
        for i in self._choices:
            # 這樣無論用戶POST上來但是CHOICES的 Key 還是Value 都能被接受
            if i == data or self._choices[i] == data:
                return i
        raise serializers.ValidationError("Acceptable values are {0}.".format(list(self._choices.values())))

to_representation

序列化器的每個字段實際都是由該字段類型的to_representation方法決定格式的,可以通過重寫該方法來決定格式。

class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = '__all__'

    def to_representation(self, instance):
        representation = super(ArticleSerializer, self).to_representation(instance)
        representation['category'] = CategorySerializer(instance.category).data
        representation['tags'] = TagSerializer(instance.tags, many=True).data
        return representation
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章