Как создать сразу несколько связанных объектов в Django Rest Framework? - PullRequest
1 голос
/ 11 апреля 2019

У меня есть следующая модель в моей модели 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)

Так что в основном у меня есть две модели, Room и Match с Match, имеющим внешний ключ от комнаты.Теперь я хочу создать оба этих объекта одновременно, но я не могу сделать это, так как сначала мне нужно создать объект Room, получить его идентификатор и назначить его экземпляру Match объекта, а затем сохранить его снова.Проблема заключается в том, что если какое-либо из сохранений модели завершилось неудачно, он нарушает код.

Можно ли как-то создать объект Match и Room одновременно?

Я нашел это ссылка в Django Документация: Но я не уверен, обрабатывает ли Django это автоматически или мне нужно обрабатывать это.

Заранее спасибо !!!

Ответы [ 3 ]

1 голос
/ 11 апреля 2019

Вы можете использовать атомарные транзакции , чтобы сохранить оба объекта или ни одного, если что-то не так.

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()

Если что-то внутри транзакции завершится неудачно, ничего не будет сохранено.

1 голос
/ 11 апреля 2019

Вам придется справиться с этим самостоятельно, если ваши сериализаторы вложены.

Как это может выглядеть, это следующее.Это полностью предположение, так как у меня нет существующих сериализаторов для работы, но я надеюсь, что это поможет вам понять цель.

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метод, который также упоминался в документации, на которую вы ссылались.

0 голосов
/ 11 апреля 2019

Вы можете просто использовать:

try:
    room = Room.objects.create(...)
    Match.objects.create(room=room, ...)
except:
    print('Catch exception here...')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...