Django表单:隐藏模型字段?

18

我有一个Form。我想包含一个返回模型的隐藏字段。我会在视图中设置它的值;我只需要它在下一页中被提交。

在表单类中应该使用什么字段?

2个回答

29

返回一个模型实例?这是指一个隐藏字段吗?

forms.HiddenInput 小部件可以实现,无论是在一个外键字段还是字符字段中存放一个模型实例ID。

class MyForm(forms.Form):
    hidden_2 = forms.CharField(widget=forms.HiddenInput())
    hidden_css = forms.CharField(widget=forms.MostWidgets(attrs={'style': 'display:none;'}))

我想让这个工作最快的方法是

class MyForm(forms.Form):
    model_instance = forms.ModelChoiceField(queryset=MyModel.objects.all(), widget=forms.HiddenInput())

form = MyForm({'model_instance': '1'})
form.cleaned_data['model_instance']

但如果你打算只指定一个项目,我不喜欢提供MyModel.objects.all()的想法。

似乎为了避免这种情况,您需要使用较小的QuerySet来重写表单__init__。

我认为我更喜欢老式的方式:

class MyForm(forms.Form):
    model_instance = forms.CharField(widget=forms.HiddenInput())

    def clean_model_instance(self):
        data = self.cleaned_data['model_instance']
        if not data:
            raise forms.ValidationError()
        try:
            instance = MyModel.objects.get(id=data)
        except MyModel.DoesNotExist:
            raise forms.ValidationError()
        return instance

不要认为ForeignKey是一个有效的表单字段...它是一个模型字段。我希望它返回一个模型实例而不是一个整数(当我稍后使用form.cleaned_data['field']检索它时)。 - mpen
forms.MostWidgets的意思是大多数可用的小部件? - fanny
@fanny 是的,你可以通过设置样式属性来简单地隐藏小部件,但使用HiddenInput()会更合理。 - Yuji 'Tomita' Tomita

2

Yuji的答案中使用了一个在表单上的clean_model_instance方法,如果你只在代码库中执行一次,那么这种方法是可以的。如果你需要经常执行此操作,则可以实现自定义模型字段来提高效率。

以下是我所拥有的代码:

from django import forms

class ModelField(forms.Field):

    Model = None

    def prepare_value(self, value):
        """Inject entities' id value into the form's html data"""
        if isinstance(value, self.Model):
            return value.id
        return value

    def to_python(self, value):
        """More or less stolen from ModelChoiceField.to_python"""

        if value in self.empty_values:
            return None

        try:
            value = self.Model.objects.get(id=value)
        except (ValueError, self.Model.DoesNotExist):
            raise forms.ValidationError('%s does not exist'
                                         % self.Model.__class__.__name__.capitalize())

        return value

如果您使用它作为基础类,然后使用自己的模型进行特殊化,那么它就成为了一个有用的基础。例如:
# In app/fields.py
from .models import CustomModel

class CustomModelField(ModelField):

    Model = CustomModel

然后,您可以与当前所需的任何小部件配对使用:
# in app/forms.py
class MyForm(forms.Form):

    hidden_custom_model_field = CustomModelField(widget=forms.HiddenInput())

    other_widget_custom_model_field = CustomModelField(widget=MyCustomWidget())

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接