2016-02-12 97 views
2

我有一個表示財務模型的Django模型。該模型與另一組包含財務數據的模型有一對多的關係。在我的數據庫中,我將這些值存儲在美元($)中,但是當我使用這些模型時,我希望能夠在歐元和英鎊之間進行轉換。Django - 在一對多關係中更改相關對象的值

因此,我在我的模型中添加了一個名爲convert_to_ccy(rate)的方法,如果我調用它,我希望它也轉換相關模型(通過此一對多關係)。這是一個非常簡單的例子來說明我正在嘗試做什麼。

class main_model_example(models.Model): 

    INCLUDE_IN_CCY_CONVERSION = ['value_field_1', 'value_field_2' etc...] 

    # FIELD DEFINITIONS 
    date = models.DateField() 
    value_field_1 = models.DecimalField(max_digits=20, decimal_places=2, default=0.00) 
    value_field_2 = models.DecimalField(max_digits=20, decimal_places=2, default=0.00) 
    ...etc... 

    # METHODS 
    def convert_to_ccy(self, rate): 
    """Converts $ fields""" 
     for field in self._meta.get_all_field_names(): 
      if field in self.INCLUDE_IN_CCY_CONVERSION: 
       value = getattr(self, field) 
        if value != None: 
        setattr(self, field, float(value)/rate) 

     # NOW CONVERT THE RELATED MODELS 
     for position in self.the_related_model_set.all(): 
      position.convert_to_ccy_rate(rate) 


# THE RELATED MODEL 
class the_related_model(models.Model): 

    INCLUDE_CCY_CONVERSION = ['yet_another_finacial_field'] 

    main_model_example = models.ForeignKey(main_model_example, on_delete=models.CASCADE) 
    yet_another_financial_field = models.DecimalField(max_digits=20, decimal_places=2, default=0.00) 
    ...and so on.... 

    def convert_to_ccy(self, rate): 
    """Converts $ fields""" 
     for field in self._meta.get_all_field_names(): 
      if field in self.INCLUDE_IN_CCY_CONVERSION: 
       value = getattr(self, field) 
        if value != None: 
        setattr(self, field, float(value)/rate) 

這個工作,並轉換正確的領域。在我的代碼(views.py等)中,我傳遞了保留我設置的新值的主模型(即以歐元)。但是,當我再次從相關模型中獲取信息時(通過使用model.the_related_model_set.all()的主模型,這些值重新變爲USD。我假設這是因爲xxx_set.all()方法再次從數據庫中檢索模型(尚未更新),我想要的是一旦我更新了相關模型,讓它們留在內存中,所以當我再次使用它們時,保留更新後的值。一套我已經閱讀文檔和瀏覽的問題,但似乎無法找到類似的話

所以我有兩個問題:

  1. 我想實現的是什麼? I.e更新內存中的相關(一對多)模型,傳遞主模型(進行更多計算),然後在稍後再次參考相關模型時獲取更新值。

或者是否需要將所有相關模型從主模型上取下並將它們分配給我必須通過主模型傳遞的變量?

  1. 事實上,我這樣做是不好的?即有主模型方法調用相關模型的方法?我對我的實施並不太舒服,這常常表明有更好的方法。

任何意見,以更好的方式來實現這一點,將不勝感激。

謝謝。

+0

不知道的錯誤,但不會要保持各自的貨幣價值,只有當你想顯示做轉換用戶?如果您現在有歐元物品並將其轉換爲美元,那麼明天當美元價值發生變化時,您的數據庫信息不正確。 – flakes

+0

是的,很好的問題。對不起,如果我不清楚。因此,我只會在向用戶展示時進行轉換 - 例如,當用戶單擊「查看報告」時,我將數據從數據庫中提取出來(以美元爲單位進行預先計算),獲取當前匯率,轉換爲歐元,然後向用戶展示(通過我標記的一些額外計算)。該數據庫僅以美元填充。現在,我可以編寫一個自定義過濾器來在模板一側進行轉換,但由於我在報告中顯示的字段數量很多(幾十個和幾十個),因此我覺得在視圖方面最好這樣做。 – rioubenson

+1

值得一提的是,當我進行貨幣轉換時,我不希望它傳播到數據庫。 – rioubenson

回答

3

對不起,但我有困難的時候跟在你的榜樣;儘管我認爲這是你想要的。

一個django Queriest有一個.update()方法,可以傳遞新的屬性來更新,並且值將會持續。

my_django_class.objects.all().update(my_class_attr=new_value) 

要獲得您的查詢設置,您可以在查詢中使用相關名稱。 Django默認生成它們,但我發現最好明確地定義它們。這This stack question addresses them well

這樣一來,你的方法是這樣的(如果我讀它的權利):

def _update_currancies(self): 
    Some_other_model(_the_related_name__field = main_model).update(attr = new_value) 

,我覺得這是更好,當一個請求觸發不更新表。通常,我只需添加兩個其他字段,並且每次輸入值更改(本例中爲USD)時,都可以使用方法更新附加字段(可以通過覆蓋保存方法來完成)。

您的情況下,它應該是這樣的:

class main_model_example(models.Model): 
    us_number = models.DecimalField(max_digits=20, decimal_places=2, default=0.00) 
    eur_number = models.DecimalField(max_digits=20, decimal_places=2, default=0.00) 
    ccy_number = models.DecimalField(max_digits=20, decimal_places=2, default=0.00) 

    def _update_currancies(self): 
     #update and set new currency values 
     #e.g. self.eur_number = self.us_number * .96 

    def save(self, *args, **kwargs): 
     self._update_currancies() 
     super(main_model_example, self).save(*args, **kwargs) 
+0

嗨,尼克。感謝你的回答。如果你發現很難遵循我的例子,那麼就加強這一事實,即我可能做錯了/複雜的事情。我瞭解您的回覆,但問題是我不想在美元兌換爲其他貨幣時堅持更改。轉換爲其他貨幣僅用於向用戶呈現的結束報告。所以我想要做的就是更新主模型實例和相關模型上的值(通過一對多關係),因爲我將它從視圖傳遞到模板,但不會觸及底層數據。 – rioubenson

+1

我明白了。在這種情況下。我會用django-Tastypie。它是一個通常用於編寫django項目和更多API的庫。您可以覆蓋模型資源的脫水方法,以實時生成新貨幣,而不會觸及您的實際數據庫。 –