A煤n no tienes acceso a esta clase

Crea una cuenta y contin煤a viendo este curso

Validaci贸n de formularios

27/37
Recursos

Para aprender a validar los campos de un formulario vamos a actualizar el registro de usuarios.
Hasta este momento el script de validaci贸n del formulario Signup est谩 escrito directamente en la vista, y a pesar de que no genera ning煤n error, puede convertirse en un problema, as铆 que lo recomendable es separarlo. Crearemos un nuevo form con la clase forms.Form, tambi茅n vamos a introducir un nuevo concepto relacionado con formularios: los widgets.

Los widgets en Django, son una representaci贸n de elementos de HTML que pueden incluir ciertas validaciones. Por default todos los campos son requeridos. Los datos depurados se pueden consultar con self.cleaned_data['_nombre_del_field_']

Aportes 33

Preguntas 17

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesi贸n.

Si alguien quiere ocultarle el label y a帽adir bootstrap a cada input deben especificar label = False y usar attrs dentro del respectivo widget

username = forms.CharField(label=False,min_length=4,max_length=50, widget = forms.TextInput(attrs={'placeholder':'username','class': 'form-control','required': True}))

De esta manera queda id茅ntico al formulario anterior

Para que quede exactamente igual que el formulario anterior pueden copiar y pegar el siguiente codigo, si usaron los mismos nombres de variables. Si no, renombrenlas.

username = forms.CharField(label=False,min_length=4,max_length=50, widget = forms.TextInput(attrs={'placeholder':'Nombre de usuario','class': 'form-control','required': True}))

    password = forms.CharField(label=False,max_length=70, widget=forms.PasswordInput(attrs={'placeholder':'Escribe tu contrase帽a','class': 'form-control','required': True}))

    password_confirmation = forms.CharField(label=False,max_length=70, widget=forms.PasswordInput(attrs={'placeholder':'Confirma tu contrase帽a','class': 'form-control','required': True}))

    first_name = forms.CharField(label=False,min_length=2,max_length=50,widget = forms.TextInput(attrs={'placeholder':'Nombres','class': 'form-control','required': True}))

    last_name = forms.CharField(label=False,min_length=2,max_length=50,widget = forms.TextInput(attrs={'placeholder':'Apellidos','class': 'form-control','required': True}))

    email = forms.EmailField(label=False,min_length=6,max_length=70,widget=forms.EmailInput(attrs={'placeholder':'Correo electr贸nico','class': 'form-control','required': True}))

OJO, buen curso pero se les olvid贸 hablar de los Model Forms, que si bien pueden ser un poco m谩s complejos (init, validators, update, super(), args, kwargs鈥) son herramientas poderosas para gestionar data. M谩s informaci贸n :
https://docs.djangoproject.com/en/2.2/topics/forms/modelforms/#

Para conservar los estilos de bootstrap lo que hice fue modificar la propiedad widget de la siguiente manera (users/forms.py)

class SignupForm(forms.Form):
    """Sign up form."""
    username = forms.CharField(
        min_length=4,
        max_length=50,
        widget=forms.TextInput(
            attrs={
                'placeholder': 'Username',
                'class': 'form-control',
                'required': True
                }
        )
    )
    password = forms.CharField(
        min_length=6,
        max_length=70,
        widget=forms.PasswordInput(
            attrs={
                'placeholder': 'Password',
                'class': 'form-control',
                'required': True
            }
        )
    )
    password_confirmation = forms.CharField(
        min_length=6,
        max_length=70,
        widget = forms.PasswordInput(
            attrs={
                'placeholder': 'Password Confirmation',
                'class': 'form-control',
                'required': True
            }
        )
    )

    first_name = forms.CharField(
        min_length=3,
        max_length=50,
        widget=forms.TextInput(
            attrs={
                'placeholder':'First name',
                'class': 'form-control',
                'required': True
                }
            )
        )
    last_name = forms.CharField(
        min_length=3,
        max_length=50,
        widget=forms.TextInput(
            attrs={
                'placeholder': 'Last name',
                'class': 'form-control',
                'required': True
                }
        )
    )

    email = forms.CharField(
        min_length=6,
        max_length=70,
        widget=forms.EmailInput(
            attrs={
                "placeholder": "email",
                "class": "form-control",
                'required': True
            }
        )
    )
	.
	.
	.
	.
}

Y en el template llamar铆a as铆 a la vista. (template/users/signup.html)

{% extends "users/base.html" %}

{% block head_content %}
    <title>PlatziGram Sign up</title>
{% endblock %}

{%block container %}
    {% if error %}
        <p class="alert alert-danger">{{ error }}</p>
    {% endif %}
    <form action="{% url 'signup' %}" method="POST">
        {% csrf_token %}
        {% for elem in form %}
            <div class="form-group">
                {{ elem }}
            </div>
        {% endfor %}
        <button class="btn btn-primary btn-block mt-5" type="submit">Register!</button>
    </form>
{% endblock %}

Yo tenia entendido que la funci贸n _save _ solo podia ser utilizado si se hereda de ModelForms, de hecho, a mi as铆 como explica no me esta funcionando, me sale el siguiente error:

鈥橲ignupForm鈥 object has no attribute 'save鈥

Python y Django mantienen una fuerte filosof铆a en DRY (Don鈥檛 Repeat Yourself) y lo que hemos visto en este curso con los forms de Django rompe toooooda esa filosof铆a, creo que bien pueden aplicarse librer铆as como Django Crispy Form (https://django-crispy-forms.readthedocs.io/), que hace una integraci贸n con los Forms, validaciones, y sobre todo Bootstrap de una forma incre铆blemente simple.

Si en lugar de forms.Form se utilizaran forms.ModelForm ser铆a todav铆a m谩s sencillo.

No est谩 de m谩s conocer c贸mo se har铆a de manera 鈥渕anual鈥, pero llegar al final de la secci贸n de forms y no ver el funcionamiento de un ModelForm me deja con una sensaci贸n de que algo falt贸, la verdad es que esperaba un poco m谩s.

Platzi y sus cursos tipicos donde solo dicen, se hace esto y esto, ah y esto hace esto, esta clase esta mala鈥 no hay fundamentos ,no se entiende

Se me ocurri贸 esta manera para que una vez que el usuario haya hecho sign up, este haga login y haga redirect al feed

En (users/views)

def signup_view(request):
    """Sign up view."""
    if request.method == 'POST':
        form = SignUpForm(request.POST)
        if form.is_valid():
            form.save()
            user = authenticate(
				request, 
				username=form.cleaned_data['username'],								 									 
    				password=form.cleaned_data['password']
	    )
            login(request, user)
            return redirect('feed')
    else:
        form = SignUpForm()

    return render(
        request=request,
        template_name='users/signup.html',
        context={'form': form}
    )

les comparto una libreria que hace mas facil la creacion de forms dinamicos con estilos y atributos custom https://github.com/jazzband/django-widget-tweaks

adem谩s mi codigo usando el mismo

{% extends 'users/base.html' %}

{% load widget_tweaks %}

{% block head_content %}
    <title>
      Platzigram Signup
    </title>    
{% endblock head_content %}


{% block container %}

  {% if errors %}
    <p class="alert alert-danger">{{errors}}</p>
  {% endif %}
  <h1 class="text-center">
    Sign up!
  </h1>
  <form action="{% url 'signup' %}" method="POST" >
    {% csrf_token %}

    {% for field in form  %}
      <div class="form-group">
        {% render_field field|add_error_class:"is-invalid" placeholder=field.label class+="form-control" %}
        {% if field.errors %}
          <div class="invalid-feedback">
            {% for error in field.errors %}{{ error }}{% endfor %}
          </div>
        
        {% endif %}
      
      </div>
    {% endfor %}

    
    <button class="btn btn-primary btn-block mt-5" type="submit">
      Register
    </button>


  </form>
{% endblock container%}

perfecto que dimamico el template form {{ form.as_p }} , investigare mas sobre ello con el fin que el dise帽o sea mas bonito pero asi de funcional de implementar

Alguien sabe Porqu茅 el profesor usa forms.CharField en lugar de forms.EmailField?? en el form?

Asi me siento con este curso 鈥淪omos la copia de la copia que el profesor esta haciendo鈥,

Este curso me esta desanimando鈥 esperaba los secretos de django orientado al backend pero casi todo est谩 enfocada al front 馃槮

como en 11:44 ,sin ganas de ense帽ar, sin motivacion, sin preocuparse de que los estudiantes entiendan, solo es una exposicion de lo que es Django

La simplicidad del c贸digo es genial鈥
Mucho m谩s legible que antes

Hola. He tenido dudas respecto a la logica de, por ejemplo, la funcion signup.

Lo que yo entiendo, y agradeceria si de estar mal, alguien me lo pudiera explicar correctamente, es que, al poner en la url /users/signup/ el view que se va a llamar es la funcion signup, esta view lo que hace es verificar si el metodo del request es POST, yt si lo es, almacenar en una variable form los datos de la peticion de tipo POST (que entiendo es generada por el template signup.html al darle submit al formulario) para posteriormente guardarla con el metodo save() que la guarda directamente hacia la base de datos especificada en settings. Como en primera instancia este request no es de tipo POST, porque viene de llamar directamente la URL (No estoy seguro si es de tipo GET(?)), entonces llama en la variable form a la clase (validacion de formularios de Django) SignupForm para que valide los campos del formulario en el template signup.html que es llamado por render en al respuesta de la funcion(?)

Tengo algunas dudas, primeramente, si mi plateamiento es correcto, claro y en segundo lugar, de estar en lo correcto, por indentacion de python, el return de la funcion se ejecuta DESPUES del if que pregunta si la peticion es de tipo request. Verdad? Por que no se llama al template justo al inicio de la vista, para que se llame directamente el formulario y solo se pregunte si la peticion es de tipo POST una vez se haya llenado el formulario y este haya cambiado la peticion a POST.

Yo como lo entiendo es que primero pregunta si es de tipo POST el request, como no lo es, llama el template con el formulario y la validacion del formulario para que cambien el tipo de request a POST y luego vuelve apreguntar si es POST, si lo es, y se ejecuta el resto del if. Parece que no es el camino mas directo.

Muchas gracias si leen esa explicacion tan larga y me pueden aclarar esa pequena duda jeje.

def signup(request):
    """Signup View"""

    if request.method == 'POST':
        form = SignupForm(request.POST)
        if form.is_valid:
            form.save()
            return redirect('login')
    else:
        form = SignupForm()

    return render(
        request = request,
        template_name = 'users/signup.html'
        context = 
        )```

Les dejo el formulario con las clases de bootstrap.

 username = forms.CharField(min_length=4, max_length=50,
    widget=forms.TextInput(attrs={'class':'form-control','placeholder':'Username'})
    )

    password = forms.CharField(
        max_length=70,
        widget=forms.PasswordInput(attrs={'class':'form-control','placeholder':'Password'})
    )
    password_confirmation = forms.CharField(
        max_length=70,
        widget=forms.PasswordInput(attrs={'class':'form-control','placeholder':'Password'})
    )

    first_name = forms.CharField(min_length=2, max_length=50,
    widget=forms.TextInput(attrs={'class':'form-control','placeholder':'First Name'})
    )
    last_name = forms.CharField(min_length=2, max_length=50,
    widget=forms.TextInput(attrs={'class':'form-control','placeholder':'Last Name'})
    )

    email = forms.CharField(
        min_length=6,
        max_length=70,
        widget=forms.EmailInput(attrs={'class':'form-control','placeholder':'Email Addres'})
    )

Para mostrar las validaciones del formulario de signup de la misma manera que en el de update_profile hice lo siguiente:

templates/users/signup.html

...

<div class="form-group">
            <input
              class="form-control {% if form.username.errors %}is-invalid{% endif %}"
              type="text"
              placeholder="Username"
              name="username"
              value="{% if form.errors %}{{ form.username.value }}{% endif %}"
            />
            <div class="invalid-feedback">
                {% for error in form.username.errors %}
                    {{ error }}
                {% endfor%}
            </div>
        </div>

...

users/forms.py

...

def clean(self):
        """Verify password confirmation match."""

        data = super().clean()

        password = data['password']
        password_confirmation = data['password_confirmation']

        if password != password_confirmation:
            ex = forms.ValidationError('Passwords do not match.')
            self.add_error('password', ex)
            self.add_error('password_confirmation', ex)
            raise ex

        return data

...

Hasta ahora el curso ha sido exelente

Podemos eliminar el label especificando este como vac铆o:

username = forms.CharField(label="")

Excelente clase!

Me surgi贸 una pregunta. C贸mo se har铆a cuando en el mismo template hay dos formularios?

why clean_ ?

A煤n cuando usamos el 鈥榝orm鈥 diretactamente en el template:

{{ form.as_p }}

Podemos agregar clases con la app de 'widget_tweaks鈥
Aqu铆 hay un tutorial de como usarlo:
https://platzi.com/tutoriales/1318-django/4060-utilizando-bootstrap-4-con-django-forms-y-widget-tweaks/

Un minimo detalle:Pienso que para el logout tambien deberia agregarse el @login required

Me recomiendan mucho en vez de crear los diccionarios con los corchetes usar el m茅todo de python dict() 驴que pensas sobre eso?

En que momento el profe cargo los post en el administrador de django?

Estimada comunidad, encontr茅 una forma de agregarle las clases a los campos desde el propio formulario (users/forms.py):

class SignUpForm(forms.Form):
    usermame = forms.CharField(min_length=5, max_length=50, widget = forms.TextInput(attrs={'class':'form-control'}))
    password = forms.CharField(max_length=140, widget = forms.PasswordInput(attrs={'class':'form-control'}))
    password_confirmation = forms.CharField(max_length=140, widget = forms.PasswordInput(attrs={'class':'form-control'}))
    first_name = forms.CharField(min_length=5, max_length=50, widget = forms.TextInput(attrs={'class':'form-control'}))
    last_name = forms.CharField(min_length=5, max_length=50, widget = forms.TextInput(attrs={'class':'form-control'}))
    email = forms.CharField(min_length=4, max_length=70, widget = forms.EmailInput(attrs={'class':'form-control'}))```

Referencia: http://www.learningaboutelectronics.com/Articles/How-to-add-a-class-or-id-attribute-to-a-Django-form-field.php#:~:text=and%20id%20attributes.-,In%20order%20to%20add%20a%20class%20or%20id%20attribute%20to,%3D%7B'class'%3A'some_class'%7D.

Les dejo mi codigo de como mostrar el error ya que todos los codigos que aparecian abajo no me servian.

{% block container %}
    {% if form.errors %}
        {% for field in form %}
            {% for error in field.errors %}
                <div class="alert alert-danger alert-dismissible fade show" role="alert">
                    {{ error|escape }}
                    <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>
            {% endfor %}
        {% endfor %}
        {% for error in form.non_field_errors %}
            <div class="alert alert-danger alert-dismissible fade show" role="alert">
                {{ error|escape }}
                <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
        {% endfor %}
    {% endif %}
    <form method="POST" action="{% url 'signup' %}">
        {% csrf_token %}

        {% for field in form %}
            <div class="form-group">
                {{ field }}
            </div>
        {% endfor %}

        <button class="btn btn-primary btn-block"type="submit">Register</button>
    </form>
    <p class="form-text mt-2">If you already have an account <a href="{% url 'login' %}">Log in!</a></p>
{% endblock %}

Buenas noches!! C贸mo se pudiera ingresar multiples datos a una tabla desde un documento Excel??

Sumamente bello el final de la clase. La manera de agrupar vistas, forms, y templates. Me gust贸 un mont贸n.

Para aprender a validar los campos de un formulario vamos a actualizar el registro de usuarios.
Hasta este momento el script de validaci贸n del formulario Signup est谩 escrito directamente en la vista, y a pesar de que no genera ning煤n error, puede convertirse en un problema, as铆 que lo recomendable es separarlo. Crearemos un nuevo form con la clase forms.Form, tambi茅n vamos a introducir un nuevo concepto relacionado con formularios: los widgets.

Los widgets en Django, son una representaci贸n de elementos de HTML que pueden incluir ciertas validaciones. Por default todos los campos son requeridos. Los datos depurados se pueden consultar con self.cleaned_data[鈥nombre_del_field鈥橾

Excelente, pero como todo es de cuidado, muy buen ejercicio