Django4 中文入门教程 Django4.0 执行查询-复制模型实例

2024-02-25 开发教程 Django4 中文入门教程 匿名 4

尽管没有用于复制模型实例的内置方法,但可以轻松地创建复制所有字段值的新实例。在最简单的情况下,您可以将 ​pk ​设置为 ​None ​并将 ​_state.adding​ 设置为 ​True​。使用我们的博客示例:

blog = Blog(name='My blog', tagline='Blogging is easy')
blog.save() # blog.pk == 1
blog.pk = None
blog._state.adding = True
blog.save() # blog.pk == 2

若你使用了集成,事情会更复杂。考虑下 ​Blog ​的一个子类:

class ThemeBlog(Blog):
theme = models.CharField(max_length=200)
django_blog = ThemeBlog(name='Django', tagline='Django is easy', theme='python')
django_blog.save() # django_blog.pk == 3

由于继承的工作原理,您必须将 ​pk ​和 ​id ​都设置为 ​None​,并将 ​_state.adding​ 设置为 ​True​:

django_blog.pk = None
django_blog.id = None
django_blog._state.adding = True
django_blog.save() # django_blog.pk == 4

该方法不会拷贝不是模型数据表中的关联关系。例如, ​Entry ​有一个对 ​Author ​的 ​ManyToManyField ​关联关系。在复制条目后,你必须为新条目设置多对多关联关系。

entry = Entry.objects.all()[0] # some previous entry
old_authors = entry.authors.all()
entry.pk = None
entry._state.adding = True
entry.save()
entry.authors.set(old_authors)

对于 ​OneToOneField ​关联,你必须拷贝关联对象,并将其指定给新对象的关联字段,避免违反一对一唯一性约束。例如,指定前文复制的 ​entry​:

detail = EntryDetail.objects.all()[0]
detail.pk = None
detail._state.adding = True
detail.entry = entry
detail.save()