Django REST framwork 报 NOT NULL constraint failed 的处理

我碰到这个问题由来是,在某个 model 里,foo_id、bar_id 两个字段都是别的表里的外键,但是在 serializer 里我又不想显示 foo_id,而想显示 foo_id 所代表的真正的意义

  1. class FooBarRelationshipSerializer(serializers.HyperlinkedModelSerializer):
  2.     foo = serializers.SerializerMethodField()
  3.     bar = serializers.CharField(write_only=True, required=False)
  4.     def get_foo(self, obj):
  5.         return Foo.objects.get(pk=obj.foo_id).name  # foo_id 来自 urls.py 里的相关 router 的定义
  6.     def validate(self, data):
  7.         del data['bar']
  8.         return data
  9.     class Meta:
  10.         model = FooBarRelationship
  11.         fields = ('foo', 'bar')

通过上面这段代码能很好地达到我的目的。好,问题来了,我想把 foo_id 和 bar_id 的关系存入表中,如果用 foo_id 和 bar_id 的话,request.data 里必然存在输入的 bar_id,但是我的实际输入是 bar,我必须要重载 validate 方法,把 bar 去掉,那么我在 views.py 里手动把 bar 对应的 bar_id 取到,然后塞进 request.data 里好了。然后

  1. serializer = self.get_serializer(data=request.data)
  2. if serializer.is_valid(raise_exception=True):
  3.         serializer.save(foo_id=foo_id)

想得挺好,运行时却报了 NOT NULL constraint failed 的错!!!

网上搜了半天,没有什么结果,提供的答案都是告诉你检查一下是不是有必填的字段没有给数据。但真正碰到这个问题的,而且还寄望通过搜索解决问题的,基本上都会先保证必填的字段里有数据,可现在数据都有了,为什么还会报这个错???

我打印了 FooBarRelationshipSerializer 里用 foo_id 和 bar_id 时的 request.data 和现在的 request.data,里面的数据一模一样!!!但是就是前者的 serializer.save 能成功,后者报错。。。

思来想去,可能同样的 request.data,但经过 serializer = self.get_serializer(data=request.data) 后,serializer 会不同,谁知道 get_serializer 里有什么鬼(不看源码了)。尝试直接把 bar_id 作为参数传给 save 方法,就像这样 serializer.save(foo_id=foo_id, bar_id=bar_id),结果当然是成功存入数据库。哈哈。

Topic: 技术