• django之 rest_framework 序列化 model 外键时的处理方式


    实践代码:

    外键为   ManyToManyField  时:

    class Role(models.Model):
        """
        角色
        """
        name = models.CharField(verbose_name='角色名称', max_length=32, unique=True)
        permissions = models.ManyToManyField('Permission', verbose_name='权限', blank=True)
        desc = models.CharField(verbose_name='描述', max_length=50, blank=True)
    
        class Meta:
            verbose_name = '角色'
            verbose_name_plural = verbose_name
            ordering = ['id']
    
        def __str__(self):
            return self.name
    
    class User(AbstractUser):
        id = models.AutoField(verbose_name="用户ID", primary_key=True)
        username = models.CharField(max_length=32, verbose_name="姓名", unique=True)
        password = models.CharField(max_length=128, verbose_name="密码")
        email = models.EmailField(max_length=128, verbose_name="邮箱", unique=True)
        role = models.ManyToManyField(Role, verbose_name='角色', blank=True)
        
        class Meta:
            verbose_name = '用户信息'
            verbose_name_plural = verbose_name
            db_table = 'users'
        
        def __str__(self):
            return self.username
    
    ### serializers
    class UserInfoSerializer(serializers.ModelSerializer):
        """
           用户信息
        """
        role = serializers.SlugRelatedField(many=True, read_only=True, slug_field="name")    #### slug_field="name",选择序列号需要展示的属性 ,name及 Role表中的name字段
        class Meta: 
    model
    = User fields = "__all__"
    depth
    = 1

    外键为  ForeignKey   时。只需要将   many=True  去掉。

    参考资料:

    https://blog.csdn.net/chexiansheng/article/details/89339025

    https://blog.csdn.net/weixin_30376453/article/details/98360039

    在定义数据的序列化器时,外键(即所属的分类)字段如何序列化?

    对于关联字段,可以采用以下几种方式:

    1、PrimaryKeyRelatedField

    此字段将被序列化为关联对象的主键。type = serializers.PrimaryKeyRelatedField(label=‘分类’, read_only=True)

    type = serializers.PrimaryKeyRelatedField(label=‘分类’, queryset=BookInfo.objects.all())

    指明字段时需要包含read_only=True或者queryset参数:
    •包含read_only=True参数时,该字段将不能用作反序列化使用
    •包含queryset参数时,将被用作反序列化时参数校验使用

    2、 StringRelatedField

    此字段将被序列化为关联对象的字符串表示方式(即__str__方法的返回值)
    type = serializers.StringRelatedField(label=‘分类’)

    3、SlugRelatedField

    此字段将被序列化为关联对象的指定字段数据
    type = serializers.SlugRelatedField(label=‘分类’, read_only=True, slug_field=‘bpub_date’)
    slug_field指明使用关联对象的哪个字段

    4、使用关联对象的序列化器

    hbook = BookInfoSerializer()
    此字段只可以用GET方法

    5、重写to_representation方法

    序列化器的每个字段实际都是由该字段类型的to_representation方法决定格式的,可以通过重写该方法来决定格式。
    注意,to_representations方法不仅局限在控制关联对象格式上,适用于各个序列化器字段类型。
    定义一个新的关联字段:
    class TypeRelateField(serializers.RelatedField):
    “”“自定义用于处理分类的字段”""
    def to_representation(self, value):
    return ‘Book: %d %s’ % (value.id, value.btitle)
    指明type为typeRelateField类型
    type = typeRelateField(read_only=True)

    6.HyperlinkedRelatedField

    可以用于使用超链接表示关系的目标

    例如,以下序列化程序:
    
    class AlbumSerializer(serializers.ModelSerializer):
    tracks = serializers.HyperlinkedRelatedField(
    many=True,
    read_only=True,
    view_name=‘track-detail’
    )
    
    class Meta:
        model = Album
        fields = ('album_name', 'artist', 'tracks')

    将序列化为这样的表示:

    {
    ‘album_name’: ‘Graceland’,
    ‘artist’: ‘Paul Simon’,
    ‘tracks’: [
    ‘http://www.example.com/api/tracks/45/’,
    ‘http://www.example.com/api/tracks/46/’,
    ‘http://www.example.com/api/tracks/47/’,
    …
    ]
    }

    默认情况下,此字段是读写的,但您可以使用该read_only标志更改此行为。

    many参数

    如果关联的对象数据不是只有一个,而是包含多个数据,如想序列化分类TypeInfo数据,每个TypeInfo对象关联的商品GoodInfo对象可能有多个,此时关联字段类型的指明仍可使用上述几种方式,只是在声明关联字段时,多补充一个many=True参数即可

    例如:

    class BlogListSerializer(serializers.Serializer):
        id = serializers.IntegerField()
        user = BlogUserInfoSerializer()
        title = serializers.CharField()
        like_user = serializers.ManyRelatedField(serializers.SlugRelatedField(slug_field="username", source="user_id"), queryset=User.objects.all(), source="follow")
        topic_name = serializers.SlugRelatedField(slug_field="name", source="topic", queryset=Topic.objects.all())
        create_at = serializers.DateTimeField()
     
    class Blog(models.Model):
        follow = models.ManyToManyField(User, verbose_name="关注", related_name="follow_blog")
        user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="blog")
        title = models.CharField(max_length=100)
        content = models.TextField(max_length=200000)
        topic = models.ForeignKey(Topic, null=True, verbose_name="话题", on_delete=models.CASCADE)
        create_at = models.DateTimeField(verbose_name="创建时间", auto_now_add=True)

    class Topic(models.Model):
        name = models.CharField(verbose_name="名称", max_length=100)
        create_at = models.DateTimeField(verbose_name="创建时间", auto_now_add=True)

    返回结果如下:

    {
                "id": 158,
                "user": {
                    "id": 50,
                    "avatar": "https://xxx.xxx.cn/media/191b6193972a439e9886187f249bd2d9.jpg",
                    "username": "语家",
                    "sex": 2
                },
                "title": "想开个童装店?",
                "like_user": [
                    "13800138000"
                ],
                "topic_name": "#你们攒钱为了什么#",
                "create_at": "2018-10-15 16:21:36"
    }
  • 相关阅读:
    Java进阶之并发初探
    Java进阶之HashMap剖析
    Java进阶之反射
    Linux常用命令
    海量数据处理算法与面试题
    一些刷题时总结的重要知识点
    一些Java刷题时的小知识点
    九章算法知识点与题目总结(不定时更新...)
    c++设计模式之状态模式
    c++设计模式之抽象工厂模式
  • 原文地址:https://www.cnblogs.com/deny/p/14899679.html
Copyright © 2020-2023  润新知