1

I have following model in my Django Model

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)

So basically I have two models, Room and Match with Match having a foreign key to a room. Now I want to create both of these objects at once, but I can not do it as first I have to create Room object get the id of it and assign it to Match object instance and then save it again. Problem with this is that if any of the model save is failed, it breaks the code.

Is there any way I can create both Match and Room object at once?

I have found this reference in Django Documentation: But I am not sure whether Django handle it automatically or do I need to handle it.

Thanks in advance!!!

3 Answers 3

1

You can use atomic transactions to save both objects or none if something fails.

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

If something inside the transaction fails nothing will be saved.

Sign up to request clarification or add additional context in comments.

1 Comment

Is there any way to do it via serializers?
1

You'll need to handle it yourself if your serializers are nested.

What it may look like is the following. This is entirely a guess since I don't have existing serializers to work off of, but I hope it'll help you understand the goal.

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)

You'll also need to handle the update method which was also mentioned in the documentation you linked to.

4 Comments

Will this be an atomic transaction? I mean if lets say room is created but match object failed to created. Will it be reversible?
I believe Django wraps the whole request in a transaction by default.
so what is the advantage of using transaction.atomic() as in @gdef_ answer
Looks like I'm wrong. It's defaulted to false. docs.djangoproject.com/en/2.2/ref/settings/… You can read more about Django's transaction management here: docs.djangoproject.com/en/2.2/topics/db/transactions/…
0

You can simply use:

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

1 Comment

But will it be atomic? I mean if lets say room is created but match object failed to created, then I want Room object to get destroyed as well

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.