关于DRF外键序列化的显示问题

  • 首先说明一下遇到的问题,我创建了三个模型,具体关系如下:
class Device(models.Model):
    device_name = models.CharField(max_length=20, verbose_name='设备名称', db_index=True)
    device_ip = models.GenericIPAddressField(verbose_name='IP地址',max_length=255,db_index=True)
    device_username = models.CharField(verbose_name='用户名',max_length=20,blank=True,null=True)
    device_password = models.CharField(verbose_name='登录密码',max_length=10,blank=True,null=True)
    device_port = models.IntegerField(verbose_name='端口号')

    create_time = models.DateTimeField(auto_now_add=True, verbose_name='添加时间')

    user = models.ForeignKey(UserInfo,verbose_name='添加人',on_delete=models.CASCADE,blank=True)

    class Meta:
        verbose_name_plural = verbose_name = '设备管理'


class Soft(models.Model):
    soft_name = models.CharField(verbose_name='软件包名称', max_length=50, db_index=True)
    soft_version = models.CharField(verbose_name='软件包版本',unique=True,db_index=True,max_length=255)

    create_time = models.DateTimeField(auto_now_add=True,verbose_name='添加时间')

    class Meta:
        verbose_name_plural = verbose_name = '软件信息'


class Project(models.Model):
    project_name = models.CharField(max_length=50, verbose_name='项目名称', db_index=True)
    create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    user = models.ForeignKey(UserInfo, verbose_name='创建者', related_name='project_user',on_delete=models.CASCADE,blank=True)
    device = models.ForeignKey(Device,verbose_name='测试设备',related_name='project_device',on_delete=models.CASCADE,blank=True)
    soft = models.ForeignKey(Soft,verbose_name='测试软件',related_name='project_soft',on_delete=models.CASCADE,blank=True)

    class Meta:
        verbose_name_plural = verbose_name = '项目管理'
  • 在序列化过程中,根据官方文档,当我想嵌套显示外键数据时,使用了官网上推荐的做法:
class ProjectSerializer(serializers.ModelSerializer):

    soft = SoftSerializer(read_only=True)
    device = DeviceSerializer(read_only=True)
    user = UserSerializer(read_only=True)
  • 上图中的三个字段对应模型中的三个外键,在该设置下,*当进行序列化输出时,可以正常显示,但是当使用post新建时,会出现 device_id cannot be null的错误提示,我相信soft会出现同样的问题。
  • 简单说一下为什么会出现上面的问题,使用当我们在调用 serializer.save()方法时,需要相应的数据已经创建,但是 ID字段应该是需要当对象创建后才会生成,所以导致无法保存。可参考下面的两个链接。
  • https://github.com/encode/django-rest-framework/issues/2964)
  • https://stackoverflow.com/questions/46805662/collections-ordereddict-object-has-no-attribute-pk-django-rest-framework
  • 知道了问题的原因,基本可以锁定是在序列化器中 def create(self, validated_data):方法出了问题。
  • 解决方法:
        try:
            '''
                第一个 try 方法解决了嵌套序列化的创建问题
            '''
            soft_id = self.initial_data.get('device', None)
            device_id = self.initial_data.get('soft',None)
            soft = Soft.objects.get(id=soft_id)
            device = Device.objects.get(id=device_id)
        except Soft.DoesNotExist or Device.DoesNotExist:
            raise serializers.ValidationError('软件包或设备不存在,请重新确认')
         validated_data.update(user=request.user,device=device,soft=soft)
         instance = super(ProjectSerializer, self).create(validated_data)
         return instance
  • 首先,我不知道为什么当我通过表单传递device,soft参数时,
	soft = SoftSerializer(read_only=True)
    device = DeviceSerializer(read_only=True)
    user = UserSerializer(read_only=True)

validated_data中为什么会导致数据不见,当我把上面的三个序列化器注释掉时,参数则会显示出来,有知道的小伙伴可以在评论区说一下,先谢过了,但是我们仍然可以通过self.initial_data取到前端传入的初始数据,通过这种方式我们手动到数据库中取到相应的对象,并更新validated_data,之后再创建就不会出现问题了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值