【问题标题】:Saving objects and their related objects at the same time in Django在 Django 中同时保存对象及其相关对象
【发布时间】:2017-04-12 11:14:09
【问题描述】:

在 Django 中,有没有办法创建一个对象,创建它的相关对象,然后一次性保存它们?

例如,在下面的代码中:

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

我创建了一个 Post 对象。然后我还想创建和关联我的 Tag 对象。我想避免保存帖子然后保存标签,因为如果 post.save() 成功,那么 tag.save() 失败,我会留下一个没有标签的帖子。

在 Django 中有没有办法一次保存所有这些,或者至少可以加强数据完整性?

【问题讨论】:

  • 这不就是交易的用途吗?

标签: python django django-models django-orm


【解决方案1】:

transactions 救援!

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')]

附带说明:我认为您真的想要PostTag 之间的多对多关系...

【讨论】:

  • 您需要保存标签或使用Tag.objects.create(...)
【解决方案2】:

覆盖保存...

class Post(models.Model):

    ...

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

这样您就不必一遍又一遍地编写事务。如果你想使用事务,只需在 save 方法中实现它,而不是循环。

【讨论】:

  • 不错的想法,但没有正确实施。你需要调用 super 两次。 Herehere 是两个例子。
  • 我不同意。他们正在做超级多次,因为这就是他们的逻辑设置方式。调用 super 多少次都没关系。从技术上讲,您甚至根本不必调用 super 方法。我的逻辑是:做超级帖子,然后在超级帖子之上做你的事情,然后返回结果。您只是在添加超级帖子中发生的事情。您提供的示例实际上正在做与此问题中想要的完全不同的事情。它只是碰巧使用了它覆盖的方法。这是非常无关的。
  • 问题是当我尝试实现这个解决方案时,post 是一个NoneType 对象。这可能是因为 save() method 没有返回任何东西。我刚刚找到了good answer here
  • 你说得对,保存不返回任何东西。我修改了我的答案。你仍然只需要调用一次。只是 self 是 Post 对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-29
  • 2011-03-23
  • 1970-01-01
  • 1970-01-01
  • 2010-11-30
  • 2013-01-29
相关资源
最近更新 更多