Los formularios son solo una herramienta para simplificar y acelerar (el desarrollo de) el proceso de obtención de datos POST de la solicitud. Una forma manual sería hacer request.POST.get('somefield')
para todos los campos que hay en algún formulario HTML. Pero Django puede hacer mejor que eso ...
En su esencia, una clase de formulario tiene una serie de campos y lleva a cabo estas tareas: entradas HTML
- de visualización,
- recopilar y validar los datos cuando el usuario lo somete,
- si los campos no validan, devuelven los valores junto con los mensajes de error en HTML,
- si todos los campos validan, proporcionan
form.cleaned_data
diccionario como una manera conveniente de acceder a estos valores a la vista.
Con estos valores, podría crear manualmente una nueva instancia de MyModel
y guardarla. Por supuesto, tendría que definir un campo en el formulario para cada campo en el modelo de MyModel.
Esto significa que, básicamente, me podía hacer algo como esto:
(perdóname por no probar este código, así que no puedo dar fe de que es 100% correcto)
models.py:
class MyModel(models.Model):
field1 = models.CharField(max_length=40, blank=False, null=False)
field2 = models.CharField(max_length=60, blank=True, null=True)
forms.py:
class FormForMyModel(forms.Form):
form_field1 = forms.CharField(max_length=40, required=True)
form_field2 = forms.CharField(max_length=60, required=False)
views.py:
def create_a_my_model(request):
if request.method == 'POST':
form = FormForMyModel(request.POST)
if form.is_valid():
my_model = MyModel()
my_model.field1 = form.cleaned_data.get('form_field1', 'default1')
my_model.field2 = form.cleaned_data.get('form_field2', 'default2')
my_model.save()
else:
form = FormForMyModel()
context_data = {'form': form}
return HttpResponse('templtate.html', context_data)
(esto podría escribirse con unas pocas líneas de código menos, pero debe ser lo más claro posible)
¡Observe que no hay relación entre los Campos del modelo y los Campos del formulario! Tenemos que asignar manualmente valores a la instancia de MyModel al crearlo.
El ejemplo anterior describe el flujo de trabajo de formulario genérico. A menudo se necesita en situaciones complejas, pero no en una tan simple como es este ejemplo.
Para este ejemplo (y un montón de ejemplos del mundo real), Django puede hacer mejor que eso ...
Se puede notar dos cuestiones molestas en el ejemplo anterior:
- tengo para definir los campos en
MyModel
y los campos en FormForMyModel
por separado. Sin embargo, hay una gran similitud entre esos dos grupos (tipos) de campos, por lo que es una especie de trabajo duplicado. La similitud aumenta cuando se agregan etiquetas, validadores, etc.
- creación de la instancia
MyModel
es un poco tonto, tener que asignar todos esos valores manualmente.
Aquí es donde un ModelForm entra en acción.
Estos actúan básicamente como una forma regular (en realidad, que se extendieron a partir de formas regulares), pero que me puede salvar algunos de los trabajos (Los dos problemas que acabo de delinear, por supuesto :)).
Así que de vuelta a las dos cuestiones:
En lugar de definir un formulario de campo para cada modelo de campo, simplemente definen en el model = MyModel
la clase Meta
. Esto instruye al formulario para que genere automáticamente campos de formulario a partir de los campos del modelo.
Las formas del modelo tienen save
método disponible. Esto se puede usar para crear una instancia de modelo en una línea en la vista, en lugar de asignarlo campo por campo manualmente.
Por lo tanto, vamos a hacer el ejemplo anterior con un ModelForm
:
models.py:
class MyModel(models.Model):
field1 = models.CharField(max_length=40, blank=False, null=False)
field2 = models.CharField(max_length=60, blank=True, null=True)
forms.py:
class MyModelForm(forms.ModelForm): # extending ModelForm, not Form as before
class Meta:
model = MyModel
views.py:
def create_a_my_model(request):
if request.method == 'POST':
form = MyModelForm(request.POST)
if form.is_valid():
# save the model to database, directly from the form:
my_model = form.save() # reference to my_model is often not needed at all, a simple form.save() is ok
# alternatively:
# my_model = form.save(commit=False) # create model, but don't save to database
# my.model.something = whatever # if I need to do something before saving it
# my.model.save()
else:
form = MyModelForm()
context_data = {'form': form}
return HttpResponse('templtate.html', context_data)
la esperanza que esto aclare el uso de Django forma un poco.
Una nota más: está perfectamente bien definir Campos de formulario en ModelForm
. Estos no se usarán en form.save()
, pero aún se puede acceder con form.cleaned_data
como en un formulario regular.
lea el tutorial https://docs.djangoproject.com/en/dev/intro/tutorial04/?from=olddocs/ y https://docs.djangoproject.com/en/dev/topics/forms/?from = olddocs –
He visto estos dos artículos y volveré a leerlos. Esperaba comprender las relaciones entre formularios, vistas y plantillas, y cómo crear una lista desplegable. Supongo que tal vez solo me lleve tiempo para digerir ... si alguien más puede dedicar algo de tiempo a explicar esto, ¡sería muy feliz! – Oli