2011-01-14 30 views
17

Mam Form. Chcę dołączyć ukryte pole, które zwraca model. Ustawię jego wartość w widoku; Po prostu potrzebuję go, aby został wysłany na następną stronę.Django Forms: Ukryte pole modelu?

Jakiego pola mam użyć w klasie formularza?

Odpowiedz

26

Ukryte pole, które zwraca model? Więc identyfikator instancji modelu?

Widget forms.HiddenInput powinno wystarczyć, czy na polu FK lub Charfield umieścić instancji modelu identyfikator.

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

Przypuszczam najszybszy sposób na zdobycie tej pracy jest

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'] 

Ale nie podoba mi się pomysł dostarczenia MyModel.objects.all(), jeśli zamierzasz określić jeden element w każdym razie.

Wygląda na to, że należy unikać tego zachowania, należy zastąpić formularz __init__ mniejszym QuerySet.

Chyba wolę staroświecki sposób:

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

Nie myśl 'ForeignKey' jest ważne pole formularza ... to pole modelu. Wolałbym, aby zwróciła instancję modelu niż liczbę całkowitą (gdy odzyska ją później za pomocą 'form.cleaned_data ['field']') – mpen

+0

Haha, masz absolutną rację .. przepraszam za to :) –

+0

formularze.MostWidgets ? czyli większość dostępnych widżetów? – fanny

2

Podejście w odpowiedzi Yuji wykorzystuje metodę clean_model_instance na formularzu, który jest w porządku, jeśli tylko kiedykolwiek to robi raz w swojej bazie kodu. Jeśli robisz to częściej, możesz skorzystać z implementacji niestandardowego pola modelu.

Jest to kod mam:

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 

Jeśli używasz, że jako klasy bazowej, a następnie specjalizować się go z własnych modeli to staje się użytecznym oparty. Na przykład:

# In app/fields.py 
from .models import CustomModel 

class CustomModelField(ModelField): 

    Model = CustomModel 

Następnie można powiązać to z czymkolwiek widget trzeba w czasie:

# in app/forms.py 
class MyForm(forms.Form): 

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

    other_widget_custom_model_field = CustomModelField(widget=MyCustomWidget())