2016-04-03 79 views
1

我有一些麻煩,我的第一個Django項目,它必須是一個常見的/容易解決一個!作爲一個背景,我正在構建一個用於追蹤治療預約的應用程序。大多數數據結構非常簡單,除了需要ManyToMany的一個實例外,還有一箇中介(通過)模型。正如你可以在我的models.py中看到的,有三個模型與我遇到的問題有關。聯繫人模式用於存儲客戶的聯繫信息。案例模型是處理一件工作/工作的概念。任何特定的案例都可以有多個會話,依此類推。通常情況下,案例可能有兩個或更多聯繫人將他們之間的賬單分開。因此,需要具有中間模型的ManyToMany存儲特定聯繫人將支付的賬單的百分比。 models.pyDjango通用視圖ManyToMany與「通過」模型

class Contact(models.Model): 
    first_name = models.CharField(max_length=200) 
    last_name = models.CharField(max_length=200) 
class Case(models.Model): 
    invoicees = models.ManyToManyField(Contact, through='Invoicees_Members', through_fields=('case','contact'),null=True, blank=True) 
class Invoicees_Members(models.Model): 
    contact = models.ForeignKey(Contact, on_delete=models.CASCADE) 
    case = models.ForeignKey(Case, on_delete=models.CASCADE) 
    invoice_percentage = models.IntegerField(validators = [MinValueValidator(1), MaxValueValidator(100)],null=True, blank=True) 

我已經做了計算器以及如何處理保存表單提交的其他網站搜索周圍的不少。最常見的解決方案似乎是我試圖在下面實施的。你會注意到我試圖使用通用的基於類的視圖(在這種情況下是CreateView)。

views.py

class CaseCreate(CreateView): 
    model = Case 
    success_url = '/cases/' 
    fields = '__all__' 
    def form_valid(self, form): 
     self.instance = form.save(commit=False) 
     for contact in form.cleaned_data['invoicees']: 
      invoicee = Invoicees_Members() 
      invoicee.case = self.instance 
      invoicee.contact = contact 
      invoicee.save() 
     return super(ModelFormMixin, self).form_valid(form) 

不幸的是,表單提交導致以下錯誤:「異常值:保存()禁止,以防止數據損失,由於未保存的相關對象‘案例’」。我的假設是,出於某種原因form.save(commit = False)不會返回一個ID用於Invoicees_Members模型保存...

有什麼想法?這一定是微不足道的,我在這裏弄錯了。附:我試過用self.object代替self.instance,並遇到同樣的錯誤。

錯誤&堆棧跟蹤:

Traceback: 

File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response 
    149.      response = self.process_exception_by_middleware(e, request) 

File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response 
    147.      response = wrapped_callback(request, *callback_args, **callback_kwargs) 

File "C:\Python27\lib\site-packages\django\views\generic\base.py" in view 
    68.    return self.dispatch(request, *args, **kwargs) 

File "C:\Python27\lib\site-packages\django\views\generic\base.py" in dispatch 
    88.   return handler(request, *args, **kwargs) 

File "C:\Python27\lib\site-packages\django\views\generic\edit.py" in post 
    256.   return super(BaseCreateView, self).post(request, *args, **kwargs) 

File "C:\Python27\lib\site-packages\django\views\generic\edit.py" in post 
    222.    return self.form_valid(form) 

File "C:\Users\danie\Documents\django-projects\office_management\officeman\views.py" in form_valid 
    40.   invoicee.save() 

File "C:\Python27\lib\site-packages\django\db\models\base.py" in save 
    651.       "unsaved related object '%s'." % field.name 

Exception Type: ValueError at /cases/add 
Exception Value: save() prohibited to prevent data loss due to unsaved related object 'case'. 

回答

0

必須保存情況的模型實例保存發票實例之前。這個錯誤是有道理的,因爲Django無法知道案例實例的ID能夠將其作爲外鍵保存在發票模型中。 self.instance = form.save(commit=True)。並檢查這個鏈接有關於這個錯誤的解釋在Django documentation

1

由ManyToMany關係引起的保存序列可能存在問題。它能夠更好地擁有來自官方文檔第一讀...

Every time you save a form using commit=False , Django adds a save_m2m() method to your ModelForm subclass. After you’ve manually saved the instance produced by the form, you can invoke save_m2m() to save the many-to-many form data.

例子:

# Create a form instance with POST data. 
>>> f = AuthorForm(request.POST) 

# Create, but don't save the new author instance. 
>>> new_author = f.save(commit=False) 

# Modify the author in some way. 
>>> new_author.some_field = 'some_value' 

# Save the new instance. 
>>> new_author.save() 

# Now, save the many-to-many data for the form. 
>>> f.save_m2m() 

閱讀保存方法與實例的完整文檔Here