我正在使用Django Rest Framework来创建一个对象。 JSON也包含嵌套对象;一组对象,用于创建和链接到"主要对象"以及应该部分更新的对象。
JSON看起来像这样:
{
"opcitem_set" : [
{
"comment" : "Test comment",
"grade" : "1",
"name" : "1a"
},
{
"comment" : "Test comment",
"grade" : "2",
"name" : "1b"
},
{
"description" : "Additional test item",
"comment" : "Additional comment",
"grade" : "1",
"name" : "extra_1"
}
],
"is_right_seat_training" : false,
"checked_as" : "FC",
"date" : "2015-10-23",
"check_reason" : "Check ride",
"opc_program" : "2",
"is_pc" : true,
"questionnaire_test_passed" : "Passed",
"pnf_time" : 2,
"other_comments_complete_crew" : "Other comments",
"other_comments_flying_pilot" : "Other comments",
"is_cat_2_training" : false,
"opc_passed" : "Passed",
"pilot" : {
"pc_valid_to" : "2015-10-23",
"id" : 721,
"email" : "jens.nilsson@nextjet.se",
"total_time" : 3120,
"medical_valid_to" : "2015-10-23"
},
"pf_time" : 2,
"aircraft_type" : "S340",
"typeratingexaminer" : 734
}
" opcitem_set"包含应该创建的OpcItem类型的对象,并且具有到主对象的ForeignKey。到目前为止,我可以通过覆盖ModelSerializer上的create()方法来实现这一点,如http://www.django-rest-framework.org/api-guide/serializers/#writable-nested-representations中所述。
然后我们得到" pilot"宾语。这将始终包含一个ID和一些其他字段来PATCH具有该ID的对象。
" typeratingexaminer"领域只是另一个" Pilot"对象,但它不应该被PATCH,只需设置为外键。
我的问题是:我可以修补(部分更新)"飞行员"以及在create()方法中,还是会破坏某种设计模式?既然它真的是PATCH而不是POST,我应该在原始请求完成后在单独的请求中执行吗?在这种情况下,我可以拥有一个跨越两个请求的事务,这样如果第二个请求失败,第一个请求将被回滚吗?
希望能够仅从客户端发送一个请求,而不是在两个请求中将其拆分。也许您可以在ViewSet中分离JSON并将其发送到不同的序列化器?
很高兴听到您的想法,我有点迷失。
答案 0 :(得分:1)
如果你没有创建一个主对象但只创建嵌套对象,你应该在序列化器中覆盖.update()方法并做一些这样的思考:
def update(self, instance, validated_data):
if 'opcitem_set' in validated_data:
opcitem_set_data = validated_data.pop('opcitem_set')
if 'pilot' in validated_data:
pilot_data = validated_data.pop('pilot')
...
for opcitem_set in opcitem_set_data:
Opcitem.objects.create(main_object=instance,
**opcitem_set)
current_pilot = self.instance.pilot
current_pilot.pc_valid_to = pilot_data.get('name', current_pilot.pc_valid_to)
...
current_pilot.save()
"""
Update instance as well if you need
"""
return instance
如果您还需要创建主对象,则需要覆盖.create()方法。但是,PATCHing pilot
将不是一个很好的方法。
答案 1 :(得分:-1)
我建议远离序列化器创建方法并在视图中构建您的广泛逻辑,您可以在需要时充分利用更简单,愚蠢的序列化器。您可以在序列化程序的create方法中进行更新,但突然间它不再是序列化程序,它更像是一个控制器,因此通过覆盖创建或更好地放置在视图代码中后方法;这种设计使您只能从客户端获得一个请求,您可以在视图代码中按摩请求数据,并使用简单的序列化程序来实例化/更新对象,并在需要时使用嵌入式数据验证。
如果您有可以分享的模型和序列化程序,我们可能会对此进行更多评论。