django正反向以及无关联数据表序列化的问题

本文深入探讨Django REST框架中序列化关联的多种方式,包括正向、反向及无关联表间的序列化处理,展示了如何利用序列化器实现数据模型间复杂关系的高效返回。

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

最近写到rest_framework返回数据,需求有正向的数据关联反向的数据关联,以及没有关系的两个表之间的数据关联起来一起返回出去
  • 我的数据模型
# 用户表
class User(models.Model):
    username = models.CharField(max_length=50, default='可爱', editable=False, verbose_name='昵称')
    status = models.BooleanField(default=0, choices=((0, '未关注'), (1, '已关注')), verbose_name='是否关注')
    level_id = models.ForeignKey(to='Level', blank=True, null=True, default=None, on_delete=models.SET_NULL, verbose_name='用户等级')
    addtime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')

# 用户级别表
class Level(models.Model):
    name = models.CharField(max_length=50,  editable=False, verbose_name='级别')
  • 正向关联的使用 (序列化器使用的serializers.ModelSerializer)
class UserSerializer(serializers.ModelSerializer):
    """用户数据序列化"""
    # 时间格式
    addtime = serializers.DateTimeField(read_only=True, format="%Y-%m-%d %H:%M:%S")
    # 获取数据库中 choices 设置的数据值
    status = serializers.CharField(source='get_status_display')
    # 通过 User 表中的 level_id 字段关联到另外的表中的 name 字段,这个是正向关联
    level_id_icon = serializers.CharField(source='level_id.name')
    class Meta:
        # 选择数据库表
        model = User
        # '__all__' 全部 如果只返回部分数据 使用元组或者列表把字段放进去  ['id', 'user', ...]
        fields = '__all__'
        

  • 反向关联的使用 (序列化器使用的serializers.ModelSerializer)
class LevelSerializer(serializers.ModelSerializer):
    """用户数据序列化"""
    # 定义一个 levels 加入user的序列化器 然后记得 User表中的外键加上 related_name = 定义的序列化器昵称
    """
    level_id = models.ForeignKey(to='Level', related_name='levels', blank=True, null=True, default=None, on_delete=models.SET_NULL, verbose_name='用户等级')
    """
    levels = UserSerializer(many=True, read_only=True)
    class Meta:
        # 选择数据库表
        model = Level
        # '__all__' 全部 如果只返回部分数据 使用元组或者列表把字段放进去  ['id', 'user', ...]
        fields = '__all__'
        
  • 无关联表的序列化器使用 (序列化器使用的serializers.ModelSerializer)
这个时候我们需要依赖强大的第三方包 django-rest-mutiple-models 

# 第一步先安装(大神请跳过)
pip install django-rest-multiple-models

# 第二部setting配置中配置一下APP

INSTALLED_APPS = (
    ....
    'drf_multiple_model',
)

# 第三步 导入
from drf_multiple_model.views import ObjectMultipleModelAPIView

# 如下两个模型
class Play(models.Model):
    genre = models.CharField(max_length=100)
    title = models.CharField(max_length=200)
    pages = models.IntegerField()
 
class Poem(models.Model):
    title = models.CharField(max_length=200)
    style = models.CharField(max_length=100)
    lines = models.IntegerField()
    stanzas = models.IntegerField()

# 序列化如下
class PlaySerializer(serializers.ModelSerializer):
    class Meta:
        model = Play
        fields = ('genre','title','pages')
 
class PoemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Poem
        fields = ('title','stanzas')
       
# 翻页器
class LimitPagination(MultipleModelLimitOffsetPagination):
    # 每页的数量
    default_limit = 10

# 如果我们使用的url是router,那这里我们就应该继承ObjectMutipleModelAPIViewset
from drf_multiple_model.viewsets import ObjectMultipleModelAPIViewSet

# 代码
class TextAPIView(ObjectMultipleModelAPIView):
    pagination_class = LimitPagination
    querylist = [
        {'queryset': Play.objects.all(), 'serializer_class': PlaySerializer},
        {'queryset': Poem.objects.filter(style='Sonnet'), 'serializer_class': PoemSerializer},
        ....

  • ObjectMultipleModelAPIView 的拓展
# 现在有一个需求,就是通过get传过来的参数进行过滤,这个时候就需要用到参数了
class TextAPIView(ObjectMultipleModelAPIView):
    pagination_class = LimitPagination
    def get(self, request, *args, **kwargs):
        	# 获取收到的数据
            uid = request.GET.get('uid', '')  # 学生id
            cid = request.GET.get('cid', '')  # 班级id
            sid = request.GET.get('sid', '')  # 学校id


            self.querylist = [
                # 在进行过滤
                {'queryset': Student.objects.filter(id=uid).order_by('-id'),
                    'serializer_class':  StudentSerializers, 'label': 'student', },
                {'queryset': Student.objects.filter(id=uid).order_by('-id'),
                    'serializer_class':  StudentSerializers, 'label': 'student', },
            ]

            return self.list(request, *args, **kwargs)
  • 有人问了,那么没有关联的表字段,要怎么加到一个序列化器中,以下是序列化器不使用外键进行序列化嵌套

class PoemSerializer(serializers.ModelSerializer):
	# 这是一个标准的序列化器 现在我们给他加上另外一个表中的数据,没有外键关联
	book_id = serializers.SerializerMethodField()

    class Meta:
        model = Poem
        fields = ('title', 'stanzas', 'book_id')
        
   	def get_book_id(self, obj):
   		# obj是个数据模型对象,可以直接. 拿到数据 
        user = book.objects.filter(id=obj.id).first() # 物理关联,不关联也行 随便
  		if user:
            data = user.name
        else:
            data = None
        return data
  • 这个方法是通过自定义一个键,通过get去拿到每个传进来的数据对象,使用SerializerMethodField进序列化关联, 参考 超链接 还有一种定义模型的方法 参考 超链接
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值