django rest框架在create中动态设置外键

时间:2016-05-20 09:42:53

标签: python django django-rest-framework

我有一个模特:

class Foo(models.Model)
  field1 = CharField(max_length=24)
  capacity = models.IntegerField(default=10)

  def used(self):
      return self.bar_set.count()

  def is_available(self):
      return self.capacity - self.used()

  @staticmethod
  def get_or_create_foo(req_count=0):
      foos = list(Foo.objects.all())
      for foo in foos:
          if foo.available() >= req_count:
              return foo
      else:
          foo = Foo() 
          foo.save()
          return foo

class Bar(models.Model)
  field1 = models.CharField(max_length=24)
  field1 = models.CharField(max_length=24)
  foo = models.ForeignKey(Foo)

现在我有这样的序列化器:

class FooSerializer(models.ModelSerializer)
  class Meta:
      model = models.Foo

class BarSerializer(models.ModelSerializer)
  count = models.IntegerField()
  field1 = models.CharField(max_length=24)
  foo = models.ForeignKey(Foo)


  class Meta:
      model = models.Bar

  def create(self, validated_data):
      instance = super(BarSerializer, self).create(validated_data)
      instance.foo = Foo.get_or_create_foo(validated_data['count'])
      instance.save()
      return instance

问题是instance = super(Bar, self).create(validated_data)在这一行我得到和例外:

Traceback (most recent call last):
  File "/home/webmaster/prj/venv/lib/python3.4/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/home/webmaster/prj/venv/lib/python3.4/site-packages/django/db/backends/sqlite3/base.py", line 318, in execute
    return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: NOT NULL constraint failed: app_bar_foo_id

传递给BarSerializer的数据是这样的(注意这里没有发送foo,因为它需要动态填充):

{
    "count": 5,
    "field1": "some text"
}

我猜是因为调用super会创建一个实例并在没有FK的情况下保存它,因为它没有在请求中传递并在那里失败,当实例化它时,在Bar中填充字段foo的工作是什么? BarSerializer

1 个答案:

答案 0 :(得分:1)

不确定super(BarSerializer, self)中的create()来电,我会这样做

def create(self, validated_data):
    instance = BarSerializer(**validated_data)
    instance.foo = Foo.get_or_create_foo(validated_data['count'])
    instance.save()
    return instance