2010-04-06 30 views
14

Me gustaría crear un formulario que incluya campos de dos modelos separados, junto con algunos otros campos regulares (no modelo). El formulario creará una instancia de cada modelo. Yo no piensa Puedo usar formularios en línea para esto, ya que no quiero incluir todos los campos de ambos modelos.Obtiene el campo de formulario de Django del campo modelo

Me gustaría crear el campo de formulario sin codificar el tipo de campos del modelo.

Sé que puedo obtener un campo de formulario de un campo modelo usando model_field.formfield(). Pero, ¿cómo puedo obtener el campo de modelo específico?

Mi primera solución:

def get_fields(model_class): 
    fields = {} 
    for f in model_class._meta.fields: 
     fields[f.name] = f 

class MyForm(forms.Form): 
    foo_name = get_fields(Foo)['name'].formfield() 
    bar_name = get_fields(Bar)['name'].formfield() 
    other_field = ... 

¿Existe un equivalente de get_fields ya? ¿Es una mala idea? Me incomoda confiar en el atributo modelo _meta. ¿O estoy yendo sobre esto de una manera completamente equivocada?

+0

Su solución me suena razonable, Altho, no veo por qué usted no desea codificar los 2 campos; quizás obtienes los modelos dinámicamente. –

+0

Quiero evitar la codificación forzada del tipo de campo de formulario en caso de que alguna vez cambie el tipo del campo de modelo correspondiente. ¿No estás seguro de lo que querías decir sobre cómo obtener los modelos dinámicamente ...? – harto

Respuesta

14

También puede consultar django.forms.models.fields_for_model. Eso debería darle un diccionario de campos, y luego puede agregar los campos del formulario

+0

No había notado ese método, gracias. Esa es la respuesta que estaba buscando, pero quizás la sugerencia de Casey Stark es más apropiada. – harto

11

Nunca debe tener que crear los campos usted mismo a menos que desee un comportamiento especial.

Esto debería ser tan simple como usar dos ModelForm sy Form adicionales dentro de una etiqueta <form> en su plantilla con un botón de envío.

en forms.py:

class Model1Form(forms.ModelForm): 
    class Meta: 
     model = Model1 
     fields = ('fields', 'you', 'want') 

class Model2Form(forms.ModelForm): 
    class Meta: 
     model = Model2 
     fields = ('fields', 'you', 'want') 

class ExtraFieldsForm(forms.Form): 
    extra_field = form.TextField() # or whatever field you're looking for 

en views.py:

form1 = Model1Form(request.POST or None) 
form2 = Model2Form(request.POST or None) 
form3 = ExtraFieldsForm(request.POST or None) 

if form1.is_valid() and form2.is_valid() and form3.is_valid(): 
    form1.save() 
    form2.save() 
    form3.save() 

    ...do other stuff like a redirect... 

y en la plantilla:

<form method="POST" action="">{% csrf_token %} 
    <fieldset> 
     {{ form1|as_uni_form }} 
     {{ form2|as_uni_form }} 
     {{ form3|as_uni_form }} 
     <div class="form_block"> 
      <input type="submit" value="Save both models"/> 
     </div> 
    </fieldset> 
</form> 

Estoy acostumbrado a usar Django-uni formulario, pero puede representar los campos de formulario como desee. Buena suerte con tu sitio.

+0

No se me ocurrió usar múltiples objetos 'Form' dentro de un solo elemento'

'. Gracias por la sugerencia. Lo probaré esta noche. – harto

+0

Cool. Espero que te sirva Lo he visto antes, pero esto no está probado. Es posible que necesite jugar con la lógica de vista para obtener lo que desea. –

2

Otra solución puede ser crear una 'uber'-forma que agregue las formas de modelo concretas. El formulario admite los métodos que normalmente proporciona un formulario y los reenvía a todos los formularios secundarios. Algunos serán simples, otros complicados. La gran ventaja de este enfoque es que ningún código más allá de la forma se ve afectado (código de validación del cliente y similares). El concepto no es realmente revolucionario, pero creo complicado agregarlo después. Paul

4

Ahora hay un documented API para conseguir el campo del modelo de una clase de modelo:

my_model_field = MyModel._meta.get_field('my_model_field_name') 

Aunque no está documentado oficialmente hasta Django 1.8, esto debería funcionar con versiones anteriores de Django también.

Una vez que tenga esto, se puede obtener el campo de formulario, así:

form_field = my_model_field.formfield() 
Cuestiones relacionadas