如何使用嵌套模型在django REST Framework中执行bulk_create?

时间:2015-03-20 08:01:24

标签: django-rest-framework

我对DRF比较陌生,我想弄清楚这个问题看起来与我能找到的所有文档略有不同。在我的玩具示例中,假设我在模型中拥有成千上万的人物记录,另一个拥有所有汽车的模型和另一个拥有所有其他财产的模型:

class Person(models.Model):
    first_name = models.CharField()
    last_name = models.CharField()
    zipcode = models.IntegerField()
    favorite_color = models.CharField()
    class Meta:
        unique_together = ('first_name', 'last_name', 'zipcode', 'favorite_color')

class Car(models.Model):
    person = models.ForeignKey(Person)
    carmake = models.CharField()
    carmodel = models.CharField()
    VIN = models.CharField()

class OtherProperty(models.Model):
    person = models.ForeignKey(Person)
    prop_type = models.CharField()
    prop_value = models.Integer()

假设我已经在数据库中加载了所有人员。现在我有一大批新记录显示一万人购买的所有新车。有些人买了多辆车,有些人买不到车。我想制作一个功能强大的API并为客户端程序保持简单,所以我想直接上传(通过POST调用)所有新车购买。诀窍是客户端程序没有每个Person记录的唯一主键。所以,我希望客户端提交类似这样的json POST:

[ {'person' : {'first_name':'Joe', 
               'last_name': 'Smith',
               'zipcode': 80110,
               'favorite_color': 'Blue'},
   'carmake' : 'Subaru',
   'carmodel' : 'Outback',
   'VIN' : 12345123123},
  {'person' : {'first_name':'Amy', 
               'last_name': 'Adams',
               'zipcode': 92075,
               'favorite_color': 'White'},
   'carmake' : 'BMW',
   'carmodel' : '325ic',
   'VIN' : 987165334},
   .... 10,000 more records... ]

现在,我有一个解决方案,我使用views.py来读取request.data,验证Person字段是否包含验证内容,将QuerySet写入Person模型以加载所有Person主键如果并非所有Person实例都已存在,则返回错误。然后我根据request.data创建一个新的dict,但所有的人子代替了新发现的主键。然后我调用CarSerializer,它有一个使用django函数bulk_create的list_serializer_class的Meta字段(根据文档:http://www.django-rest-framework.org/api-guide/serializers/#customizing-multiple-create)。这很有效。

但是,我认为Person查找代码不属于Car ViewSet,对吧?而且,我可能会复制django / DRF已经通过验证做的很多事情。此外,现在我需要将该代码复制并粘贴到OtherProperty ViewSet以执行相同的Person主键查找。实际上,我有更多的模型对Person模型有一个ForeignKey,我知道我不应该复制/粘贴所有主键查找和验证代码。

所以,我的问题是,我在哪里可以放置Person主键查找代码?它似乎是一个序列化程序应该做的事情,但我不是想保存任何新的Person实例。并且,由于我正在创建大量“Cars”(或“OtherProperty”)实例,我需要将其作为ListSerializer(bulk_create)调用,因此我认为我不能仅仅依赖于嵌套关系并期望它工作。我错过了一个明显的解决方案吗?

感谢您的任何建议。

修改

我有几个想法作为潜在的解决方案:

  1. 创建一个未附加到Person模型的PersonLookup序列化程序。此序列化程序将具有Person字段,接受完整的request.data并使用序列化程序功能进行验证,但是然后它将返回原始的request.data而不是创建任何记录,而不是详细的Person信息,以便返回的数据可以由ViewSet处理并发送到Car或OtherProperty Serializers。

  2. 向Person模型添加一个唯一字段,该字段是所有非唯一字段的下划线分隔串联。然后客户端将能够通过串联创建这些字段,并且request.data不会嵌套。实际上,这可能不起作用,因为bulk_create将需要主键,而不是某些唯一字段,我认为(?)。另一个问题是,我将存储两次所有Person字段,一次是在唯一名称中,另一次是在各个字段中。也许有一个经理技巧来解决这个问题。

1 个答案:

答案 0 :(得分:0)

  

所以我认为我不能只依赖嵌套关系并期望它能够正常工作。

不,你不能。因为DRF(从3.0版开始)不再支持任何类型的嵌套创建/更新(请参阅“Writable nested serialization

至于你的问题,你采取的方式是要走的路。唯一可能的改进是缓存您的Person pks,以供进一步使用。另外,在创建Cars时,您只需要访问一次数据库。之后,将从缓存中检索每个Person的pk。

希望这有帮助。