2012-02-03 76 views
0

下面是簡化的示例的什麼,我想實現:手動保存的ModelForm相對外鍵

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 =無錯誤。我也嘗試瞭解django的InlineForm(在管理端)是如何工作的,但似乎他們首先保存了主產品,然後保存了ProductAttributeValue,並且如果說ProductAttributeValue保存失敗了,那麼他們很好。 對於我的情況,這是不可接受的,即我應該保存所有表格(產品和價值)或失敗。我可以肯定地從一開始就用commit = True保存,但正如我所說的,我不希望產品被保存並且不值的情況。

任何幫助表示讚賞。

+0

當然,你不能一個未保存的實例添加到另一個未保存的實例。調用'save()'然後賦值屬性有什麼問題?你是否期望它以某種方式失敗?如果你這樣做,那麼下面有關於交易的答案。我只是好奇你爲什麼在這裏期待失敗..你應該事先做驗證,以確保它不會在數據庫級別失敗。 – 2012-02-03 03:05:15

回答

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

感謝您的回答!我很好奇看看是否有其他解決方案。我已經在幾個地方使用了transaction.commit_on_success。我想它可以避免手動回滾/提交調用。 – user1039384 2012-02-03 03:32:44

0

由於在保存產品之前沒有爲您的產品生成標識,因此我認爲您不能在產品之前保存屬性。無論如何,必須先保存其中的一個 - 最好先保存產品,然後保存屬性,並添加一些邏輯來刪除產品,如果保存ProductAttributeValues由於某種原因失敗。儘管如此,我不明白爲什麼保存會在ProductAttributeValues上失敗,因爲驗證應該已經在乾淨的情況下完成了。