Django Forms:隐藏的模型字段?

时间:2011-01-14 00:23:09

标签: django

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

我应该在表单类中使用哪个字段?

2 个答案:

答案 0 :(得分:29)

返回模型的隐藏字段?那么模型实例ID?

forms.HiddenInput窗口小部件应该可以解决这个问题,无论是在FK字段还是CharField中,都可以放入模型实例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()的想法。

似乎要避免这种行为,您必须使用较小的__init__覆盖表单QuerySet

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

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

答案 1 :(得分: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())