我在django中有几个连接多对多的模型。我想在内存中创建这些模型的实例,将它们呈现给用户(通过view-templates中的自定义方法调用),如果用户满意,则将它们保存到数据库中。
但是,如果我尝试对模型实例(例如调用呈现方法)执行任何操作,则会收到一条错误消息,指出我必须先保存实例。文档说这是因为模型处于多对多的关系中。
如何向用户展示对象并允许他/她保存或丢弃它们而不会使我的数据库混乱?
(我想我可以关闭交易处理并在整个项目中自己完成,但这听起来像是一个容易出错的措施......)
THX!
答案 0 :(得分:6)
我会添加一个字段,指示对象是“草稿”还是“实时”。这样他们就会在请求,会话等方面持续存在,并且django停止抱怨。
然后,您可以过滤对象以仅在公共视图中显示“实时”对象,并仅向创建它们的用户显示“草稿”对象。这也可以扩展为允许“存档”对象(或任何其他有意义的状态)。
答案 1 :(得分:4)
我认为使用django表单可能就是答案,如this文档中所述(搜索m2m ...)。
编辑为可能遇到同样问题的其他人添加一些解释:
说你有这样的模特:
from django.db import models
from django.forms import ModelForm
class Foo(models.Model):
name = models.CharField(max_length = 30)
class Bar(models.Model):
foos = models.ManyToManyField(Foo)
def __unicode__(self):
return " ".join([x.name for x in foos])
然后你不能在未保存的Bar对象上调用unicode()。如果你想在保存之前打印出来,你必须这样做:
class BarForm(ModelForm):
class Meta:
model = Bar
def example():
f1 = Foo(name = 'sue')
f1.save()
f2 = foo(name = 'wendy')
f2.save()
bf = BarForm({'foos' : [f1.id, f2.id]})
b = bf.save(commit = false)
# unfortunately, unicode(b) doesn't work before it is saved properly,
# so we need to do it this way:
if(not bf.is_valid()):
print bf.errors
else:
for (key, value) in bf.cleaned_data.items():
print key + " => " + str(value)
因此,在这种情况下,您必须保存Foo对象(在保存这些对象之前可能会使用自己的表单进行验证),并且在保存具有多对多键的模型之前,您也可以验证这些对象。所有这些都不需要过早保存数据并弄乱数据库或处理交易......
答案 2 :(得分:0)
很晚才回答,但是wagtail的团队制作了一个名为django-modelcluster的单独的Django扩展。这是他们的CMS草案预览的动力。
它允许你做这样的事情(来自他们的自述文件):
beatles = Band(name='The Beatles')
beatles.members = [
BandMember(name='John Lennon'),
BandMember(name='Paul McCartney'),
]
然后可以像这样使用模型:
ParentalKey
在这里,ForeignKey
取代了Django的ParentalManyToManyField
。同样,他们有ManyToManyField
来取代Django的{{1}}。