2016-12-07 75 views
1

我試圖生成一個對象,允許將值存儲在標準單位中,但是會根據項目的設置以不同的單位顯示。下面是一個我需要能夠存儲房間溫度的例子。爲了便於計算,我希望數據庫值處於Kelvin狀態,但希望用戶能夠按項目要求查看/輸入F或C.Django在渲染前更改模型數據ModelForm

模型可以從表單中取值,並在保存時將它們轉換爲開爾文。我知道這可以在表單中完成,但我在這裏有其他數據輸入方法。該模型的向下版本如下:

class Room(models.Model): 
    name    = models.CharField(max_length=255)    
    temperature   = models.FloatField(default=293.15) 

    def save(self, *args, **kwargs): 
     self.temperature = convert.temperature(self.temperature, 
      from_unit=self.plant.temperature_scale) 
     super(Room, self).save(*args, **kwargs) 

我創建了一個ModelForm,用於CreateView和UpdateView。我需要ModelForm來限制其他字段的查詢集(工作正常)。在這裏,我能夠將溫度場轉化成所需的單位在CreateView的一個新的對象,但我似乎無法找到拉這一關的現有記錄

class RoomForm(ModelForm): 
    def __init__(self, plant, *args, **kwargs): 
     super (RoomForm,self).__init__(*args,**kwargs) 

     self.fields['temperature'].initial = convert.temperature(
      value=self.fields['temperature'].initial, 
      from_unit='K', 
      to_unit=self.fields['unit'].queryset[0].plant.temperature_scale) 

     self.instance.temperature = convert.temperature(
      value=self.instance.temperature, 
      from_unit='K', 
      to_unit=self.fields['unit'].queryset[0].plant.temperature_scale) 

    class Meta: 
     model = Room 
     fields = ['name', 'temperature'] 

良好的措施的方式,這裏有這種形式的觀點。

class NewRoom(CreateView): 
    model = Room 
    form_class = RoomForm 

    def get_form_kwargs(self, **kwargs): 
     form_kwargs = super(NewRoom, self).get_form_kwargs(**kwargs) 
     form_kwargs["plant"] = Plant.objects.get(slug=self.kwargs['plant']) 
     return form_kwargs  

class EditRoom(UpdateView): 
    model = Room 
    form_class = RoomForm 
    template_name_suffix = "_update_form" 

    def get_form_kwargs(self, **kwargs): 
     form_kwargs = super(EditRoom, self).get_form_kwargs(**kwargs) 
     form_kwargs["plant"] = Plant.objects.filter(slug=self.kwargs['plant']) 
     return form_kwargs 

在模板(而不是形式),我用它來正確顯示溫度。

{{ room.temperature|convert_temperature:room.plant.temperature_scale }} 

我想我需要補充,其中的ModelForm從數據庫中記錄導入數據的一部分,但我不能確定下這個現象發生在django.forms源代碼。

我試着在shell

>>> from rooms.models import * 
>>> from rooms.forms import * 
>>> room = Room.objects.first() 
>>> form = RoomForm(room.plant, instance=room) 
>>> form.instance.temperature 
20.0 
>>> form.as_p() 

和呈現形式與溫度不正確的值如下

<p> 
    <label for="id_name">Name: 
    </label> 
    <input id="id_name" maxlength="255" name="name" type="text" value="Testing" 
     required /> 
</p>\n 
<p> 
    <label for="id_temperature">Temperature: 
    </label> 
    <input id="id_temperature" name="temperature" 
     step="any" type="number" value="293.15" required /> 
</p>\n 

我使用Django版本1.10.3如果是手動調用此可能這是一個錯誤。

+0

嗨,布賴恩,你自己寫了convert.temperature,還是有沒有準備好使用的包我錯過了?我想堅持約定是否有任何:) – gabn88

+0

我寫了我自己的轉換模塊。我見過一堆Pint的參考,但是我發現語法混亂。 –

回答

0

雖然lucasnadalutti讓我在正確的位置,它沒有設法做到這一點。覆蓋傳遞給ModelForm.__init__的實例,並在更改後再次調用它。

class RoomForm(ModelForm): 

    def __init__(self, plant, *args, **kwargs): 
     super(RoomForm, self).__init__(*args,**kwargs) 

     self.instance.temperature = convert.temperature(
      value=self.instance.temperature, 
      from_unit='K', to_unit=self.fields['unit'].queryset[0].plant.temperature_scale) 

     # Override instance passed to __init__ and call super again 
     kwargs['instance'] = self.instance 
     super(RoomForm, self).__init__(*args, **kwargs) 

    class Meta: 
     model = Room 
     fields = ['name', 'temperature'] 
1

要在渲染之前修改現有記錄中的數據,請在調用父項__init__後在self.instance中執行。

def __init__(self, plant, *args, **kwargs): 
    super(RoomForm,self).__init__(*args,**kwargs) 
    self.instance.temperature = # ... 
+0

註釋掉了我當前的'self.fields ['temperature']。initial ='並將'self.instance.temperature ='添加到'__init__'的末尾,但似乎並沒有成功。 (有兩個版本在那裏讓我在我的位置) –

+0

'self.instance'給你正確的對象嗎? – lucasnadalutti

+0

在我的代碼中輸入調試語句以在終端中輸出值顯示正確答案,但在頁面上不顯示所需(即使重新啓動服務器後)。添加'print(self.instance)'會打印終端中的房間名稱。 –