我有一个Django modelForm,它排除了一些模型字段,因此当它在网页上使用时,这些字段是可用的。我想在API上使用相同的modelForm对象。
当我在网页上使用表单时,表单的呈现会考虑模型字段的默认值,表单将被呈现,并且提交的“最终”表单将包含这些值。同样地,我可以在创建过程中将初始dict传递给表单。
问题是,当您通过API公开modelForm时,没有默认值的初始呈现,导致它们显示在最终提交的表单中。这会导致is_valid
返回false,因为表单“需要”通过表单的初始呈现填充其默认值的字段。
是否有一些设置可以让表单在验证时查看这些“默认”模型值,或者我是否只需编写验证代码来考虑它们?由于模型指定了默认值,因此看起来这应该可以正常工作,但事实并非如此。
除此之外,我如何找到字段来从中提取默认值作为我验证表单的点。到目前为止,我可以找到我编写的方法和方法,例如get_completion_format_display
,但我没有看到模型类中字段的定义。
答案 0 :(得分:2)
嗯,我已经想出了这个(有效),但我希望其他人有一个更优雅的解决方案。这正是我需要它做的,并且在通过Django进行调试时,我根本没有看到任何其他方法来执行此操作。实例参数在使用之前与初始数据合并,因此证明这是一种“修复”它的无效方法。
class MyForm(forms.ModelForm):
""" Demonstrates using the default values from the data model so that form.is_valid()
will return True if the form has sufficient data (useful when using a form object with an api."""
class Meta:
model = MyModel
exclude = ('status', 'uuid', 'submitted_on', 'completed_on',
'last_attempt', 'failure_reason')
def __init__(self, data=None, files=None, *args, **kwargs):
""" Grab the default values from the model and add them to the form so it will validate """
if data:
for field in self.Meta.model._meta.fields:
if (field.default != NOT_PROVIDED
and field.name not in self.Meta.exclude
and field.name not in data:
data[field.name] = field.default
super(MyForm, self).__init__(data, files, *args, **kwargs)
答案 1 :(得分:0)
我有同样的问题,我决定在模型级解决它:
class DefaultingModelMetaClass(models.Model.__metaclass__):
def __new__(cls, name, bases, attrs):
obj = super(DefaultingModelMetaClass, cls).__new__(cls, name, bases, attrs)
for f in obj._meta.fields:
if not hasattr(f, 'orig_blank'):
f.orig_blank = f.blank
if f.has_default():
# If a default value is provided we allow blank values for the field (not-required field)
# We fill it with the default value when saved if it is still blank
f.blank = True
return obj
class DefaultingModel(models.Model):
"""
Model class which makes fields not-required if they are providing a default value.
Also fills in empty values for fields with default values on save.
"""
__metaclass__ = DefaultingModelMetaClass
class Meta:
abstract = True
def save(self, *args, **kwargs):
for f in self._meta.fields:
if f.orig_blank:
# We do not do anything with fields originally allowing blank values
continue
raw_value = getattr(self, f.attname)
if f.has_default() and raw_value in validators.EMPTY_VALUES:
setattr(self, f.attname, f.get_default())
super(DefaultingModel, self).save(*args, **kwargs)