下面是我想要实现的简化示例:
class Product(models.Model):
# some data, does not really matter
class ProductAttributeValue(models.Model):
product = models.ForeignKey('Product')
value=models.CharField(_("value"),max_length=100)
...
class ProductForm(forms.ModelForm):
def __init__(self,*args, **kwargs):
super(ProductForm, self).__init__(*args, **kwargs)
#Here, I am dynamically constructing and injecting attributes.
#my products have dynamic attributes
# the filled-in values of these attributes need to be saved as ProductAttributeValue instances
#...
def save(commit):
m = super(ProductForm, self).save(commit=False)
#looping thru my custom attributes and constructing instances
#to simplify I will just put one example
attr_val=ProductAttributeValue(product=m)
attr_val.value=self.clean_data['myval']
m.productattributevalue_set.add(attr_val)
if commit:
m.save()
# also doing m2m_save if exists
return m
因为我预计这会因product_id = None错误而失败。我也试图理解django的InlineForm(在管理端)如何工作,但似乎他们首先保存主要产品然后保存ProductAttributeValue,如果说ProductAttributeValue保存失败他们就没事了。 对于我的情况,这是不可接受的,即我应该保存所有表格(产品和价值)或失败。我当然可以从一开始就使用commit = True进行保存,但正如我所说的,我不想要一个保存产品并且没有价值的情况。
任何帮助表示感谢。
答案 0 :(得分:1)
请参阅:https://docs.djangoproject.com/en/dev/topics/db/transactions/ 我认为你可以使用手动交易来做到这一点。提交第一个保存,然后在第二个保存失败时回滚:
@transaction.commit_manually
def viewfunc(request):
...
# You can commit/rollback however and whenever you want
transaction.commit()
...
# But you've got to remember to do it yourself!
try:
...
except:
transaction.rollback()
else:
transaction.commit()
答案 1 :(得分:0)
由于在保存之前没有为您的产品生成ID,因此我认为您无法在产品之前保存属性。无论如何,必须先保存一个 - 不妨保存产品,然后保存属性,并添加一些逻辑来删除产品,如果由于某种原因保存ProductAttributeValues失败。不过,我不知道为什么保存会在ProductAttributeValues上失败,因为验证应该已经在clean中完成了。