我正在尝试生成一个对象,该对象允许将值存储在标准单元中,但根据项目的设置以不同的单位显示。以下是我需要能够存储房间温度的示例。我希望数据库值以开尔文为单位,以便于计算,但希望用户能够根据项目需要查看/输入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)
我创建了一个在CreateView和UpdateView中使用的ModelForm。我需要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 :(得分:1)
要在呈现之前修改现有记录中的数据,只需在调用父self.instance
之后在__init__
中执行此操作。
def __init__(self, plant, *args, **kwargs):
super(RoomForm,self ).__init__(*args,**kwargs)
self.instance.temperature = # ...
答案 1 :(得分:1)
虽然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']