2011-01-14 23 views
17

Tengo un Form. Quiero incluir un campo oculto que devuelve un modelo. Estableceré su valor en la vista; Solo necesito que se publique en la próxima página.Django Forms: campo de modelo oculto?

¿Qué campo se supone que debo usar en la clase de formulario?

Respuesta

26

¿Un campo oculto que devuelve un modelo? Entonces, ¿un ID de instancia modelo?

El widget de forms.HiddenInput debe hacer el truco, ya sea en un campo FK o CharField se pone un ID de instancia de modelo en el.

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

supongo que la manera más rápida de conseguir este funcionamiento está

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

Pero no me gusta la idea de suministrar MyModel.objects.all() si de todos modos va a especificar un elemento.

Parece que para evitar ese comportamiento, tendría que anular el formulario __init__ con un QuerySet más pequeño.

creo que prefiero la manera antigua:

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

No piense 'ForeignKey' es un campo de forma válida ... es un campo modelo. Prefiero que devuelva una instancia de modelo en lugar de un número entero (cuando lo recupere más tarde con 'form.cleaned_data ['field']') – mpen

+0

Jaja, tienes toda la razón ... lo siento :) –

+0

forms.MostWidgets ? que significa la mayoría de los widgets disponibles? – fanny

2

El enfoque en la respuesta de Yuji utiliza un método clean_model_instance en el formulario que está bien si estás sólo alguna vez hacer esto una vez en su base de código. Si lo hace con más frecuencia, entonces puede beneficiarse al implementar un campo de modelo personalizado.

Este es el código que tengo:

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 

Si utiliza eso como una clase base y luego se especializan con sus propios modelos entonces se convierte en un útil basada. Por ejemplo:

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

class CustomModelField(ModelField): 

    Model = CustomModel 

Luego de realizar la vinculación que con cualquier widget que necesita en el momento:

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

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

    other_widget_custom_model_field = CustomModelField(widget=MyCustomWidget()) 
Cuestiones relacionadas