Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving objects and their related objects at the same time in Django

In Django, is there a way to create a object, create its related objects, then save them all at once?

For example, in the code below:

from django.db import models


class Post(models.Model):
    title = models.CharField(max_length=255)
    body = models.CharField(max_length=255)


class Tag(models.Model):
    post = models.ForeignKey(Post)
    title = models.CharField(max_length=255)

post = Post(title='My Title', body='My Body')
post.tag_set = [Tag(post=post, title='test tag'), Tag(post=post, title='second test tag')]
post.save()

I create a Post object. I then also want to create and associate my Tag objects. I want to avoid saving the Post then saving the Tags because if a post.save() succeeds, then a tag.save() fails, I'm left with a Post with no Tags.

Is there a way in Django to save these all at once or at least enforce better data integrity?

like image 646
AdamY Avatar asked Nov 28 '16 16:11

AdamY


People also ask

How do I save multiple items in Django?

To create multiple records based on a Django model you can use the built-in bulk_create() method. The advantage of the bulk_create() method is that it creates all entries in a single query, so it's very efficient if you have a list of a dozen or a hundred entries you wish to create.

How do you save objects in Django?

Creating objects To create an object, instantiate it using keyword arguments to the model class, then call save() to save it to the database. This performs an INSERT SQL statement behind the scenes. Django doesn't hit the database until you explicitly call save() . The save() method has no return value.

What does save () do in Django?

The save method is an inherited method from models. Model which is executed to save an instance into a particular Model. Whenever one tries to create an instance of a model either from admin interface or django shell, save() function is run.

Do I need to save after create Django?

create() will automatically save, so even if you fix your error - you will still have to make sure the arguments to create fulfill the database requirements to save a record.


2 Answers

transactions to the rescue !

from django.db import transaction

with transaction.atomic():
   post = Post.objects.create('My Title', 'My Body')
   post.tag_set = [Tag(post, 'test tag'), Tag(post, 'second test tag')]

As a side note: I think you really want a many to many relationship between Post and Tag...

like image 195
bruno desthuilliers Avatar answered Nov 03 '22 04:11

bruno desthuilliers


override save...

class Post(models.Model):

    ...

    def save(self, *args, **kwargs):
        super(Post, self).save(*args, **kwargs)
        for tag in self.tag_set:
            tag.save()

This way you don't have to write the transaction thing over and over again. If you want to use transactions, just implement it in the save method instead of doing the loop.

like image 25
Ian Kirkpatrick Avatar answered Nov 03 '22 06:11

Ian Kirkpatrick