2017-04-25 41 views
0

如果一個人有兩種型號:什麼是Django 1.10+發票計算的「最佳實踐」?

class Invoice(models.Model): 
    class Meta: 
     ordering = ('-date_added',) 

    number = models.CharField(max_length=10,) 
    comments = models.TextField(blank=True, help_text="Notes about this invoice.") 
    total = models.DecimalField(max_digits=9, decimal_places=2, default="0") 
    date_added = models.DateTimeField(_('date added'), auto_now_add=True) 
    date_modified = models.DateTimeField(_('date modified'), auto_now=True) 

def __unicode__(self): 
    return "%s: total %s" % (self.number, self.total) 

class Part(models.Model): 
    for_invoice = models.ForeignKey(Invoice) 
    description = models.CharField(max_length=200, blank=True, help_text=_("Briefly describe the part.")) 
    supplier = models.CharField(max_length=100, blank=True, help_text=_("Supplier Name.")) 
    supplier_number = models.CharField(max_length=100, blank=False, help_text=_("Supplier's order number.")) 
    qty = models.DecimalField(max_digits=3, decimal_places=0, blank=False, null=False, help_text=_("How many are needed?")) 
    cost = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True, help_text=_("Price paid per unit")) 
    line_total = models.DecimalField(max_digits=9, decimal_places=2, default="0") 
    date_added = models.DateTimeField(auto_now_add=True) 
    date_modified = models.DateTimeField(auto_now=True) 

def __unicode__(self): 
    return "%s: total %s" % (self.for_invoice, self.line_total) 

首先選擇我看到的是一個可以實現「line_total」或「總」的計算模型場。但是,如果你這樣做了,那麼你不能通過「line_total」或「total」對改變列表進行排序,並且用戶希望能夠做到這一點。所以我讓它們在模型上保存起來。

讀取的Django 1.10文檔我看到4個地方代碼可被限定成計算和更新「總」和「line_total」字段:

  1. ModelAdmin.save_model(請求,OBJ,形式,變更)和ModelAdmin.save_formset(請求,形式,表單集,變更)
  2. ModelAdmin.save_related(請求,形式,表單集,變更)
  3. model.save(個體,*指定參數時,** kwargs))
  4. 保存信號

在我看來,保存信號太低級 - 綁定到單個模型保存事件,並且永遠無法訪問請求或會話。因此,嘗試整理所有「Part」記錄會很「煩人」?

同樣,看起來model.save方法也會過於細化。如果我可以使用Invoice.save方法,那將是「方便的」,因爲它可以通過Invoice.part_set.all()方便地訪問所有關聯的部分,循環該查詢集將是更新line_total的簡單方法,然後主總。但是,現在所有新的/更改的零件記錄都會保存嗎?它將無法訪問HttpRequest。

我認爲同樣適用於Admin的save_model。但是,我有一個模糊的記憶,它可能會確保相關的零件首先被保存。我在Admin中的Invoice添加/編輯頁面上使用內聯列出部件。

我剛加入ModelAdmin.save_related!我忘了那個。由於此時主發票將被保存,可能這是更新所有零件記錄的最佳位置,然後更新父項總數?

在此先感謝!

+2

你*可以*按照計算的字段進行排序。看[這個答案](http://stackoverflow.com/a/42660093/113962)。 – Alasdair

回答

0

感謝阿拉斯代爾的建議,但是,這個客戶端不想要一個完整的自定義解決方案。所以我堅持管理調整。

我正在測試使用選項2:save_related管理員的功能。代碼如下:

from decimal import Decimal 

    def save_related(self, request, form, formsets, change): 
    total = Decimal('0.00') 
    for myform in formsets: 
     for mf in myform.forms: 
     # Skip empty rows (if any): 
     if len(mf.cleaned_data) > 0: 
      # Update item line total from item quantity and price: 
      mf.instance.line_total = mf.instance.qty * mf.instance.cost 
      # Add line item total to grand total: 
      total += mf.instance.line_total 
      # re-save line item: 
      mf.instance.save() 
    # Update grand total on the invoice: 
    form.instance.total = total 
    # re-save the invoice record: 
    form.instance.save() 
    # Chain to inherited code: 
    super(InvoiceAdmin, self).save_related(request, form, formsets, change) 

對不起,變量名稱。我被深度2級的內聯表格嚇倒了。我猜第一層是一組formset(只有一個),第一個formset裏面是我的表單。一切都有。實例對象,我認爲這表明他們已經被保存。一個驚喜,因爲我認爲我讀了這個函數的默認動作是保存表單集(主表單已經保存)。

無論如何,它的作品,所以我會假設我誤解了文檔。