Django REST framwork-05-序列化关系

Posted shark_西瓜甜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django REST framwork-05-序列化关系相关的知识,希望对你有一定的参考价值。

示例 Model

# 资产表
class Asset(models.Model):
    """
    资产信息表,所有资产公共信息(交换机,服务器,防火墙等)
    """
    # objects = AssetManager()

    device_type_choices = (
        ('1', '服务器'),
        ('2', '路由器'),
        ('3', '交换机'),
        ('4', '防火墙'),
    )
    device_status_choices = (
        (1, '上架'),
        (2, '在线'),
        (3, '离线'),
        (4, '下架'),
    )

    device_type_id = models.CharField(choices=device_type_choices, default='1', max_length=1)
    device_status_id = models.IntegerField(choices=device_status_choices, default=1)

    latest_date = models.DateField(verbose_name='更新时间', null=True, blank=True)
    create_at = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    


# 服务器表
class Server(models.Model):
    """服务器信息"""
    asset = models.OneToOneField('Asset', 
           verbose_name='对应资产', null=True, blank=True,
           on_delete=models.SET_NULL)

    hostname = models.CharField(verbose_name='主机名', max_length=128, unique=True)
    manage_ip = models.GenericIPAddressField(verbose_name='管理 IP', null=True, blank=True)
    
    
# 硬盘表
class Disk(models.Model):
    """
    硬盘信息
    """
    slot = models.CharField(verbose_name='插槽位', max_length=8)
    model = models.CharField(verbose_name='磁盘型号', max_length=32)
    capacity = models.FloatField(verbose_name='磁盘容量GB')
    pd_type = models.CharField(verbose_name='接口类型', max_length=32)
    server_obj = models.ForeignKey(Server, related_name='disk',
      verbose_name='所属服务器', on_delete=models.CASCADE)

OneToOneField 一对一

通常情况下,会在页面上展示所有的资产信息列表。
此时往往希望点击某一个资产数据,会跳转到对应的资产信息。
这时做好的做法是使用 HyperlinkedRelatedField 对关系字段进行序列化。

HyperlinkedRelatedField

可以用于使用超链接表示关系的目标。
就是说可以使用一个 URI 来表示关系目标,具体看下面的图。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6PjsIuWo-1624289203405)(evernotecid://BBD579E0-7127-4377-8E81-47BEA574FA91/appyinxiangcom/25594833/ENResource/p543)]

serializers

from rest_framework import serializers

from cmdb.models import Asset, Server


class AssetSerializer(serializers.ModelSerializer):
    # 添加关系字段
    server = serializers.HyperlinkedRelatedField(
        many=False, read_only=True,
        view_name='api:server-detail'
    )
    class Meta:
        model = Asset
        fields = ["device_type_id", "device_status_id",
                  "latest_date", "create_at", "server"]
                  

class ServerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Server
        fields = ['asset','hostname', 'manage_ip',]

many=False 一对一关系时需要设置为 False, 这是默认值,但建议显示传递(易读)。

read_only=True 只用于展示,不支持修改
AssetSerializer 中添加的 server 关系字段是在 Server model 中 related_name 指定的用于反向查询的字段名。
view_name 必须的参数,用于路由的反解(reverse), 假如序列化的路由不是在项目的根路由中注册的,这个 view_name 的值需要添加上 app 的路由名称空间的名字。例如,在 api 应用中注册路由, view_name 的值应该是 ‘api:disk-detail’

ForeignKey 多对一

嵌套关系的序列化

考虑这样一个情况, 前端页面展示了 服务器 的列表,由于关于服务器的信息太多,并且还涉及到一台服务器会有多块硬盘等。

所以在一张表的一行数据表示一台服务器的所有数据显然不太合适。

此时使用 多对一个 关系就是很好的解决方案。

那希望点击一个服务器时候,会跳转到一个专门展示服务器信息的详情页面。这个页面专门用于展示这个服务器的基本信息和硬盘、内存等信息。也就是说,需要在一个页面上展示服务器表的本身的数据,还有夸表查询到的多对一关系的数据。

此种情况就可以使用 嵌套关系的序列化

serializers

from rest_framework import serializers

from cmdb.models import Disk, Server

# 定义序列化 多方 的序列化器
class DiskSerializer(serializers.ModelSerializer):
    class Meta:
        model = Disk
        fields = "__all__"

# 定义序列化 一方 的序列化器
class ServerSerializer(serializers.ModelSerializer):
    # 对关系字段进行序列化
    disk = DiskSerializer(many=True)
    class Meta:
        model = Server
        fields = ['asset','hostname', 'manage_ip', 'disk']

many=True 用于 多对一关系

disk 是在 Disk model中使用 related_name 定义的用于反向查找的字段名。

在这里插入图片描述

多对多

和多对一是一样的操作

以上是关于Django REST framwork-05-序列化关系的主要内容,如果未能解决你的问题,请参考以下文章

django之序列化数据

python Django Rest_Framework框架 模型类序列化器(ModelSerializer)详解(图文并茂版)

python Django Rest_Framework框架 模型类序列化器(ModelSerializer)详解(图文并茂版)

18-Django REST framework-使用Django开发REST 接口

带有 django-rest-auth 和 django-rest-knox 的 AttributeError - 令牌序列化器

怎么安装django rest framework