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"
}
原文地址:https://www.cnblogs.com/deny/p/14899679.html