我在我的模型中使用pickelField将csv数据序列化为数据库作为pandas数据帧。 Pickle字段不显示在管理表单上,因此我创建了一个额外的文本字段。
我正在关注向管理员表单添加自定义字段的this示例。
class ParameterDataTableAdminForm(forms.ModelForm):
# create field to accept csv text
data = forms.CharField(widget=forms.Textarea, required=True)
class Meta:
model = ParameterDataTable
def __init__(self, *args, **kwargs):
super(ParameterDataTableAdminForm, self).__init__(*args, **kwargs)
# if instance exists this is an update
if kwargs.has_key('instance'):
instance = kwargs['instance']
# repr existing data
csv_text = StringIO()
instance.values.to_csv(csv_text,index=False)
self.initial['data'] = csv_text.getvalue()
def save(self, commit=True):
model = super(ParameterDataTableAdminForm, self).save(commit=False)
# convert the data to a pandas data frame
model.values = pandas.read_csv(StringIO(self.cleaned_data['data']))
# NEED TO VALIDATE MODEL.VALUES
if commit:
model.save()
return model
class ParameterDataTableAdmin(admin.ModelAdmin):
form = ParameterDataTableAdminForm
admin.site.register(ParameterDataTable, ParameterDataTableAdmin)
问题是在运行clean方法后,model.values
被添加到模型中。我想使用模型清理方法来验证该字段。出于显而易见的原因,我试图避免在管理表单中验证模型字段。
我已经尝试在设置model.clean
后立即显式运行model.values
,但我得到一个异常而不是屏幕上的干净漂亮错误消息。
使用模型的clean方法验证字段value
并将其与表单字段values
相关联的最佳方法是什么?
编辑 - 我正在添加模型的相关部分
class ParameterDataTable(ParameterBase):
values = PickledObjectField(null=False, blank=False, verbose_name=_("values"))
def clean(self):
super(ParameterDataTable, self).clean()
if self.is_visible:
raise ValidationError(_("Datatable cannot be visible"))
if pd.isnull(self.values).any().any():
raise ValidationError(_("Found missing values."))
我正在为我的模型使用PolymorphicModel。 ParameterBase
是一个PolymorphicModel。我没有遇到任何麻烦。
答案 0 :(得分:0)
不是在表单上创建其他字段,只需为values
模型字段创建自定义表单字段,然后在此自定义字段中处理转换:
def validate_pandas_frame(value):
if pd.isnull(value).any().any():
raise ValidationError(_("Found missing values."))
class CSVTextarea(forms.Textarea):
def render(self, name, value, attrs=None):
csv_text = StringIO()
output = value.to_csv(csv_text, index=False)
return super(CSVTextarea, self).render(name, output, attrs)
class PickledCSVField(forms.Field):
widget = CSVTextarea
default_validators = [validate_pandas_frame]
def to_python(self, value):
return pandas.read_csv(StringIO(value))
class ParameterDataTableAdminForm(forms.ModelForm):
# create field to accept csv text
values = forms.PickledCSVField(required=True)
class Meta:
model = ParameterDataTable
...
修改:为表单呈现的对话添加了自定义forms.Textarea
实施
答案 1 :(得分:0)
只是一个想法,但您可以在ModelForm的clean()
方法中预先指定模型的值,而不是尝试在save()
中执行此操作方法。
这样ValidationErrors应该整齐地传播到管理员。
class ParameterDataTableAdminForm(forms.ModelForm):
# create field to accept csv text
data = forms.CharField(widget=forms.Textarea, required=True)
class Meta:
model = ParameterDataTable
def __init__(self, *args, **kwargs):
super(ParameterDataTableAdminForm, self).__init__(*args, **kwargs)
# if instance exists this is an update
if kwargs.has_key('instance'):
instance = kwargs['instance']
# repr existing data
csv_text = StringIO()
instance.values.to_csv(csv_text,index=False)
self.initial['data'] = csv_text.getvalue()
def clean(self):
# clean to initially populate cleaned_data
super(ParameterDataTableAdminForm, self).clean()
# parse cleaned_data and assign resulting pickled dataframe to values
self.instance.values = pandas.read_csv(StringIO(self.cleaned_data['data']))
# run clean again, to catch values errors
# or, even try, self.instance.clean()
super(ParameterDataTableAdminForm, self).clean()
这很难找到,但模型实例在ModelForm中的instance
下可用。
绑定到模型对象的模型表单实例将包含一个实例 属性,使其方法可以访问该特定模型 实例
https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-clean-method