restframework 序列化和反序列化外鍵


前言

  • 這是博主第一次接觸學習restframework框架,很多知識點零散不系統,在這不建議將此文作為指導方向。
  • 在此文講解前,不會說明安裝和配置信息,大家可以百度如何安裝restframework,並自行安裝成功就行。
  • 在此會講解幾種序列化和反序列化的方法,表的設計是一對多結構。

代碼實現

序列化

首先我們在models下新建兩個模型類

class User(SoftDeleteMode):
    GENDER_CHOICES = (
        ('1', '普通會員'),
        ('2', 'VIP會員')
    )
    name = models.CharField(max_length=100, verbose_name='昵稱')
    phone = models.CharField(max_length=11, verbose_name='手機號', unique=True)
    password = models.CharField(max_length=255, verbose_name='密碼')
    level = models.CharField(max_length=20, choices=GENDER_CHOICES, verbose_name='用戶身份')

    class Meta:
        db_table = 'user'
        verbose_name = '用戶表'
        app_label = 'polls' # 標記是屬於哪個app的models,該屬性常用於models的分層
        ordering = ['-id']  # 根據id倒序排列

    # 調用時返回自身的屬性,不然都是顯示xx object
    def __str__(self):
        return self.name


class BookInfo(SoftDeleteMode):
    title = models.CharField(max_length=20, verbose_name='名稱')
    read = models.IntegerField(default=0, verbose_name='閱讀量')
    comment = models.IntegerField(default=0, verbose_name='評論量')
    author = models.ForeignKey(User, on_delete=models.CASCADE, error_messages={"does_not_exist": "作者不存在"}) # 外鍵

    class Meta:
        db_table = 'tb_books'  # 指明數據庫表名
        verbose_name = '圖書'  # 在admin站點中顯示的名字
        app_label = 'polls'  # app_lable的值為APP的名稱,這樣就可以將models定義到多個文件中了。

    def __str__(self):
        """定義每個數據對象的顯示信息"""
        return self.title

每個模型定義一個serializers.ModelSerializer

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'name', 'phone', 'level']


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = BookInfo
        fields = ['id', 'title', 'read', 'comment','author']

通過postman請求我們的接口可以看到,author作為外鍵序列化后,返回的是User里的id。(忽略字段_create_time和_update_time)

如果我們想要返回具體外鍵里的值,應該怎么看呢。

  • 第一種方法: 在Meta中定義一個深度depth=1
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = BookInfo
        # 取出所有的字段
        fields = ['id', 'title', 'read', 'comment','author']
        depth = 1
  • 實現效果,可以看到會把外鍵相關的表數據序列化出來,而且是不可控的把表數據字段讀了出來。但我們可能並不需要那么多的數據,包括用戶密碼等字段。

  • 第二種方法: 我們定義一個get_author()方法
class BookSerializer(serializers.ModelSerializer):
    author = serializers.SerializerMethodField() 

    class Meta:
        .....
        
    
    # 在BookSerializer中我們定義一個方法,獲取外鍵對應的數據
    def get_author(self, obj):
        authors_query_set = obj.author  # 拿到所有作者信息 (obj是User對象)
        return [{"id": authors_query_set.id, "name": authors_query_set.name}]

  • 實現效果: 可以看到,按照我們定義的方法返回了值,需要什么數據可以在get_author中添加即可,想要反序列化{"author": 1}作為外鍵添加時,不得有depth=1

反序列化

可以在serializers.ModelSerializer中定義與author字段相同的屬性,並實例化serializers.PrimaryKeyRelatedField對象

class BookSerializer(serializers.ModelSerializer):
    # 必須要傳的參數,queryset查詢集,這里我們的主表是User表,所以定義了User的查詢集
    # error_messages: 錯誤提示信息,如果對象未找到對應的key:does_not_exist
    author = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), error_messages={"does_not_exist": "作者不存在"})
    
    class Meta:
        model = BookInfo
        fields = ['id', 'title', 'read', 'comment']
    
    def get_author(self, obj):
        authors_query_set = obj.author  # 拿到所有作者信息
        return [{"id": authors_query_set.id, "name": authors_query_set.name}]
    

實現效果:

  • 添加成功

  • 添加失敗


免責聲明!

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



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