【问题标题】:How do i created multiple connected objects at once in Django Rest Framework?如何在 Django Rest Framework 中一次创建多个连接对象?
【发布时间】:2019-09-02 12:28:36
【问题描述】:

我的 Django 模型中有以下模型

class Match(models.Model):

    initiator = models.ForeignKey('CustomUser', related_name='match_initiator', on_delete=models.CASCADE)
    matched_person = models.ForeignKey('CustomUser', related_name='matched_person', on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now=True)
    algo_version = models.IntegerField()
    room_no = models.ForeignKey('Room', related_name='room_match', on_delete=models.CASCADE, null=True, blank=True)


class Room(models.Model):

    name = models.CharField(max_length=20, unique=True)
    members = models.ManyToManyField(CustomUser, related_name="joined_rooms")
    created_at = models.DateTimeField(auto_now=True,editable=False)
    is_active = models.BooleanField(default=True)

所以基本上我有两个模型,RoomMatch,其中 Match 有一个房间的外键。现在我想一次创建这两个对象,但我不能这样做,因为首先我必须创建 Room 对象获取它的 id 并将其分配给 Match 对象实例,然后再次保存它。这样做的问题是,如果任何模型保存失败,它就会破坏代码。

有什么方法可以同时创建 Match 和 Room 对象吗?

我在 Django 文档中找到了这个 reference:但我不确定 Django 是自动处理它还是我需要处理它。

提前致谢!!!

【问题讨论】:

    标签: django django-models django-rest-framework django-serializer


    【解决方案1】:

    如果您的序列化程序是嵌套的,您需要自己处理。

    它可能如下所示。这完全是一种猜测,因为我没有现有的序列化程序可供使用,但我希望它可以帮助您理解目标。

    class MatchSerializer(serializers.ModelSerializer):
        room = RoomSerializer()
    
        class Meta:
            model = Match
            fields = (...)
    
        def create(self, validated_data):
            room_data = validated_data.pop('room')
            room = Room.objects.create(**profile_data)
            validated_data['room'] = room
            return super().create(self, validated_data)
    

    您还需要处理您链接到的文档中也提到的update 方法。

    【讨论】:

    【解决方案2】:

    您可以使用atomic transactions 来保存这两个对象,或者如果出现故障则不保存。

    from django.db import IntegrityError, transaction
    
    def your_function(...):
        try:
            with transaction.atomic():
                room = Room.objects.create(...)
                match = Match.objects.create(room_no=room, ...)
                ....
        except IntegrityError:
            handle_exception()
    

    如果事务中的某些内容失败,则不会保存任何内容。

    【讨论】:

    • 有没有办法通过序列化器来做到这一点?
    【解决方案3】:

    你可以简单地使用:

    try:
        room = Room.objects.create(...)
        Match.objects.create(room=room, ...)
    except:
        print('Catch exception here...')
    

    【讨论】:

    • 但它会是原子的吗?我的意思是,如果让我们说房间被创建但匹配对象未能创建,那么我希望房间对象也被销毁
    猜你喜欢
    • 2021-12-04
    • 1970-01-01
    • 2017-09-12
    • 2021-08-01
    • 2018-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多