Django之关系模型的序列化

59 篇文章 ¥19.90 ¥99.00
本文详细介绍了Django中关系模型的序列化,包括多查1和1查多的情况。在多查1中,通过在serializers中指定fields字段,可以将班级信息一并序列化。对于1查多的情况,展示了如何序列化一方查询多方的数据。同时,当需要双向序列化关系字段时,文章提到了使用serializers.RelatedField手动处理的方法,并强调了serializers类的定义顺序重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、关系模型的序列化-多查1

image-20211203115541109

1.1、模型准备

from django.db import models


# Create your models here.
class Classes(models.Model):
  name = models.CharField(max_length=20, verbose_name='班级')
  
class Student(models.Model):


  SEX_CHOICES = ((1,'男')), (2, '女')


  name = models.CharField(max_length=20, verbose_name='姓名')
  age = models.IntegerField(null=True, blank=True, verbose_name='年龄')
  sex = models.IntegerField(choices=SEX_CHOICES, default=1, verbose_name='性别')
  classes = models.ForeignKey(Classes, on_delete=models.SET_NULL,null=True,verbose_name='班级')

1.2、迁移模型

python manage.py makemigrations
python manage.py migrate

1.3、初始化数据

insert into t_class (name) values ('Python');
insert into t_class (name) values ('SQL');
insert into t_student(name,age,sex,classes) values ('BaiZhan',18,1,1);
insert into t_student(name,age,sex,classes) values ('SXT',20,2,1);

1.4、serializers

class ClassSerializer(serializers.ModelSerializer):
  class Meta:
    model = Classes
    fields = '__all__'

说明:

只是在StudentSerializer类的meta中 fields 字段中添加了 classes 字段,那么序列化时,显示的只是对应的班级的主键id,如:{"id": 3, "name": "terry", "age": 18, "sex": 1, "classes":1}

如果想序列化对应的班级的信息,那么需要在 StudentSerializer 中,重新指定 classes 字段

class StudentSerializer(serializers.ModelSerializer):
  #新增 所属班级 属性
  classes = ClassesSerializer()


  class Meta:
    model = Student
    fields = ['id', 'name', 'age', 'sex', 'classes']
  • 当前修改后的序列化内容为:{"id": 3, "name": "terry", "age": 18, "sex": 1, "classes": {"id": 1, "name": "\u4e00\u73ed"}}

测试

GET http://127.0.0.1:8000/rest_app/students/

 

二、关系模型的序列化-1查多

image-20211203115541109

以上只是显示了一对多关系中,关系多方查询1的数据的序列化,下面展示如何序列化1查多方多的数据

models:

class Student(models.Model):


  SEX_CHOICES = ((1,'男')), (2, '女')


  name = models.CharField(max_length=20, verbose_name='姓名')
  age = models.IntegerField(null=True, blank=True, verbose_name='年龄')
  sex = models.IntegerField(choices=SEX_CHOICES, default=1, verbose_name='性别')
    
  # 必须增加属性 related_name='students'
  classes = models.ForeignKey(Classes, related_name='students', null=True, on_delete=models.SET_NULL, verbose_name='班级')

serializers:

from rest_framework import serializers


from .models import Classes, Student


class StudentSerializer(serializers.ModelSerializer):
  class Meta:
    model = Student
    fields = ['id','name','age','sex']


class Class2Serializer(serializers.ModelSerializer):
  # 通过related_name反向查询的字段,创建序列化器对象
  students = StudentSerializer(many=True,read_only=True)
  class Meta:
    model = Classes
    fields = ['id','name','students']

注意

StudentSerializer 必须在 ClassesSerializer 上面

urls:

path('classes/<int:pk>/', views.classes_detail),

views:

def classes_detail(request, pk):
  try:
    classes = Classes.objects.get(pk=pk)
  except Classes.DoesNotExist:
    return HttpResponse(status=404)


  if request.method == 'GET':
    serializer = ClassesSerializer(classes)
    return JsonResponse(serializer.data)
  else:
    # 其他情况暂不处理
    return HttpResponse(status=503)

 测试

GET http://127.0.0.1:8000/rest_app/classes/1/

三、手动处理关系字段

image-20211203144408037

由于serializers类的引用关系的原因,serializers类中能只能有1方引入另1方,不如互相引入

如果业务需求,需要2个关系字段都序列化,那么就需要使用到 serializers.RelatedField 类,手动处理关系字段

serializers:

from rest_framework import serializers


from .models import Classes, Student


class StudentRelateFiled(serializers.RelatedField):
  # 重写to_representation方法,将外键关联的对象转换为指定的格式
  def to_representation(self, value):
    return {'id':value.id,'name':value.name,'age':value.age}  


class ClassSerializer(serializers.ModelSerializer):
  students = StudentRelateFiled(many=True,read_only=True)
  class Meta:
    model = Classes
    fields = ['id','name','students']


class StudentSerializer(serializers.ModelSerializer):
  # 通过外键关联的类,创建序列化器对象
  classes = ClassSerializer()
  class Meta:
    model = Student
    fields = ['id','name','age','sex','classes']

 

注意事项

  • 上面3个类的先后顺序不能错

测试:

GET http://127.0.0.1:8000/rest_app/classes2/1/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜鸟之编程

您的支持将成为我的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值