Django 未通过禁用字段-需要解决方法
我有一个表单,我想用它更新MyModel对象。在模型上有一个唯一的约束,即fieldA和fieldB。在clean方法的表单中,我检查这个唯一的约束 出于某些原因,我不得不在更新中将fieldA显示为只读。因此,fieldA不会通过。我的问题是,如果表单未验证,表单将重新显示,但我在fieldA中丢失了值 我试图重置已清理的_数据['fieldA'],但它不起作用。 你知道要改变什么吗 Forms.pyDjango 未通过禁用字段-需要解决方法,django,django-forms,Django,Django Forms,我有一个表单,我想用它更新MyModel对象。在模型上有一个唯一的约束,即fieldA和fieldB。在clean方法的表单中,我检查这个唯一的约束 出于某些原因,我不得不在更新中将fieldA显示为只读。因此,fieldA不会通过。我的问题是,如果表单未验证,表单将重新显示,但我在fieldA中丢失了值 我试图重置已清理的_数据['fieldA'],但它不起作用。 你知道要改变什么吗 Forms.py class MyModelUpdateForm(forms.ModelForm):
class MyModelUpdateForm(forms.ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
super(MyModelUpdateForm, self).__init__(*args, **kwargs)
self.fields['fieldA'].widget.attrs['readonly'] = True
self.fields['fieldA'].widget.attrs['disabled'] = True
def clean(self):
cleaned_data = self.cleaned_data
fieldA= self.instance.fieldA
fieldB = cleaned_data.get("fieldB")
if MyModel.objects.filter(fieldA=fieldA, fieldB=fieldB).count() > 0:
#try to reset fieldA, since it is not passed through, since it is disabled
cleaned_data['fieldA'] = fieldA.pk #does not work
raise forms.ValidationError('some unique validation error')
return cleaned_data
Views.py:
myModelobject = get_object_or_404(MyModel.objects, pk=mymodel_id)
if request.method == 'POST':
model_form = MyModelUpdateForm(request.POST, instance=myModelobject )
if model_form .is_valid():
....
我对表单的工作原理有点兴趣,并提出了多种解决方案,只是为了见鬼 由于您禁用的是小部件,而不是字段,因此就表单而言,它始终没有收到fieldA的任何信息,这将始终导致验证失败 尝试clean()方法对无效表单没有帮助,因为
clean()
数据用于处理
表单为HTML显示拉取数据的方式似乎是field.data
,这是从\u datadict(POST,FILES,field\u name)调用field.widget.value\u,因此它将始终查看您的POST数据
所以我认为你有几个选择。Hackrequest.POST
,Hack内部表单POST数据,或Hackvalue\u from\u datadict
黑客request.POST
:直截了当,有道理
myModelobject = get_object_or_404(MyModel.objects, pk=mymodel_id)
if request.method == 'POST':
POST = request.POST.copy()
POST['fieldA'] = myModelobject.fieldA
model_form = MyModelUpdateForm(POST, instance=myModelobject )
if model_form .is_valid():
# ...
黑客内部字典:
def __init__(self, *args, **kwargs):
super(MyModelUpdateForm, self).__init__(*args, **kwargs)
self.data.update({ 'fieldA': self.instance.fieldA })
从datadict中黑客value\u:有点可笑,但说明了从挖掘源代码中可以学到什么
def __init__(self, *args, **kwargs):
super(MyModelUpdateForm, self).__init__(*args, **kwargs)
self.fields['fieldA'].widget.value_from_datadict = lambda *args: self.instance.first_name
在这里学到了一些很酷的东西:)希望能有所帮助。我也遇到过类似的问题,我就是这样解决的
我将字段设置为隐藏:
self.fields['fieldA'].widget.attrs['style'] = 'display:none;'
在模板中,我分别显示字段值:
{{ form.fieldA.label_tag }}
{{ form.fieldA }}
{{ form.fieldA.value }}
{{ form.fieldA.errors }}
如果是fieldA,则为选择菜单:
{{ form.fieldA.label_tag }}
{{ form.fieldA }}
{% for value, title in form.fields.fieldA.choices %}
{% if value == form.fieldA.value %}
{{ title }}
{% endif %}
{% endfor %}
{{ form.fieldA.errors }}
您可以将其放在form类中,如下所示:
class MyForm(forms.Form):
MY_VALUE = 'SOMETHING'
myfield = forms.CharField(
initial=MY_VALUE,
widget=forms.TextInput(attrs={'disabled': 'disabled'})
def __init__(self, *args, **kwargs):
# If the form has been submitted, populate the disabled field
if 'data' in kwargs:
data = kwargs['data'].copy()
self.prefix = kwargs.get('prefix')
data[self.add_prefix('myfield')] = MY_VALUE
kwargs['data'] = data
super(MyForm, self).__init__(*args, **kwargs)
它的工作方式是测试是否有数据传递给表单构造函数。如果有,它会复制它(未复制的数据是不可变的),然后在继续实例化表单之前输入初始值。我在不涉及后端部分的情况下解决了此问题,您只需使用“可见性:隐藏”属性将特定类添加到forms.py中的fieldA
self.fields['fieldA'].widget.attrs['class'] = 'visibility_hidden_class'
然后,在模板中,您的form.fieldA将被隐藏,但不会在post请求中丢失
{{ form.fieldA.label_tag }}
{{ form.fieldA }}
<input type="text" value="{{ form.fieldA.value }}" disabled />
{{form.fieldA.label_tag}
{{form.fieldA}}
因此,您仍将在请求表单数据中保留form.fieldA。从视觉上看,您的字段将始终填充.fieldA.value表单。我必须解决一个类似的问题。我使用like-dinamyc formset生成新行,因此一旦选择产品,它就会显示为禁用,但我需要在视图中获取表单上的值。Jquery和JavaScript对我来说更容易,所以我生成了一个预发送事件,删除了我在表单集中使用的选择器上的禁用项。我在使用小部件select2进行此设置,因此它也适用于select2
当然,发送按钮id=“postForm”和表单id=“contractForm”的id是相同的
我使用jQuery解决了这个问题,在提交之前从所有输入中删除禁用项
$('#my_form').submit(function(){
$("#my_form :disabled").removeAttr('disabled');
});
在models.py中添加blank=True
例如:
class myModel(models.Model):
myField = models.CharField(max_length=30, blank=True)
我知道这是一个老问题,但我最近自己也遇到了这个问题。我认为最简单的解决方案是在init定义中使用“initial”:
def __init__(self, *args, **kwargs):
super(MyModelUpdateForm, self).__init__(*args, **kwargs)
self.fields['fieldA'].disabled = True
self.fields['fieldA'].initial = self.instance.fieldA
当然,这假设实例已经存在。如果需要,您可能需要添加一个“if”子句。Nice,但是如果出现复选框,您该怎么办呢。你们如何区分复选框被禁用还是未选中。我发现对输入元素使用“readonly”比破解帖子或@BehnamHeydari问题是关于使用“只读”阻止数据发送的事实。谢谢你的回答。在破解内部dict时,我得到了一个这个QueryDict实例是不可变的
异常。因此,我最终修补了来自_datadict
函数的值。
def __init__(self, *args, **kwargs):
super(MyModelUpdateForm, self).__init__(*args, **kwargs)
self.fields['fieldA'].disabled = True
self.fields['fieldA'].initial = self.instance.fieldA