2011-01-14 5 views
17

У меня есть Form. Я хочу включить скрытое поле, которое возвращает модель. Я поставлю его значение в представлении; Мне просто нужно, чтобы он был опубликован на следующей странице.Django Forms: Скрытое поле модели?

Какое поле я должен использовать в классе формы?

ответ

26

Скрытое поле, которое возвращает модель? Итак, идентификатор экземпляра модели?

forms.HiddenInput виджет должен сделать трюк, на поле FK или CharField вы поставите ли экземпляр модели идентификатор.

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 
+0

Не думает, что 'ForeignKey' является действительным полем формы ... это поле модели. Я бы предпочел, чтобы он возвращал экземпляр модели, а не целое число (когда я получаю его позже с помощью 'form.cleaned_data ['field']') – mpen

+0

Ха-ха, вы абсолютно правы .. извините за это :) –

+0

forms.MostWidgets ? что означает большинство доступных виджетов? – fanny

2

подход в ответ Юдзи использует метод 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()) 
Смежные вопросы