[英]Django alter model data before rendering ModelForm
我正在嘗試生成一個對象,該對象允許將值存儲在標准單位中,但根據項目的設置以不同的單位顯示。 以下是我需要能夠存儲房間溫度的示例。 我希望數據庫值在開爾文中以便於計算,但希望用戶能夠根據項目要求在F或C中查看/輸入。
該模型可以從表單中獲取值並將其保存為開爾文。 我知道這可以通過表格完成,但是我在這里有其他數據輸入方法。 該模型的簡化版本如下:
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源代碼中發生這種情況的地方。
我嘗試在外殼中手動調用此
>>> 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版(如果有可能是一個bug)。
要在呈現之前修改現有記錄中的數據,只需在調用父級的__init__
之后在self.instance
進行操作即可。
def __init__(self, plant, *args, **kwargs):
super(RoomForm,self ).__init__(*args,**kwargs)
self.instance.temperature = # ...
盡管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']
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.