Rewrite all forms to use Django Forms with validation
- Add ProductEditForm, EditProfileForm, ChangePasswordForm, ShippingAddressForm
- Add ResetPasswordForm, ResetPasswordPhase2Form
- Update views to use new Django Forms
- Add form validation tests (terms required, password mismatch, etc)
- Update templates to use Django Forms {{ form.as_p }}
This commit is contained in:
+354
@@ -0,0 +1,354 @@
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from .models import Category
|
||||
|
||||
|
||||
class ProductForm(forms.Form):
|
||||
name = forms.CharField(
|
||||
label="Nombre del Producto",
|
||||
max_length=200,
|
||||
required = True,
|
||||
widget=forms.TextInput(
|
||||
attrs = {
|
||||
'class': 'form-control',
|
||||
'placeholder': 'Ej: iPhone 15 Pro Max'
|
||||
}
|
||||
)
|
||||
)
|
||||
briefdesc = forms.CharField(
|
||||
label="Descripción Breve",
|
||||
max_length=250,
|
||||
required = True,
|
||||
widget = forms.TextInput(
|
||||
attrs = {
|
||||
'class': 'form-control',
|
||||
'placeholder': 'Una descripción corta para mostrar en las tarjetas de producto'
|
||||
}
|
||||
)
|
||||
)
|
||||
description = forms.CharField(
|
||||
widget=forms.Textarea(attrs={"rows": "5", "class": "form-control"}),
|
||||
max_length=5000,
|
||||
label="Descripción completa",
|
||||
required = True
|
||||
)
|
||||
price = forms.FloatField(
|
||||
label="Precio (en €)",
|
||||
required = True,
|
||||
widget = forms.TextInput(
|
||||
attrs = {
|
||||
'class': 'form-control',
|
||||
'placeholder': '15.99'
|
||||
}
|
||||
)
|
||||
)
|
||||
stock = forms.IntegerField(
|
||||
label="Stock Disponible",
|
||||
required = True,
|
||||
widget = forms.TextInput(
|
||||
attrs = {
|
||||
'class': 'form-control'
|
||||
}
|
||||
)
|
||||
)
|
||||
category = forms.ModelChoiceField(
|
||||
queryset=Category.objects.all(),
|
||||
label="Categoría",
|
||||
required=True,
|
||||
widget=forms.Select(attrs={'class': 'form-control'})
|
||||
)
|
||||
|
||||
primary_image = forms.ImageField(
|
||||
label="Imagen Principal",
|
||||
required = False,
|
||||
widget = forms.ClearableFileInput(
|
||||
attrs = {
|
||||
'class': 'form-control',
|
||||
'accept': 'image/*'
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class ProductEditForm(forms.Form):
|
||||
name = forms.CharField(
|
||||
label="Nombre del Producto",
|
||||
max_length=200,
|
||||
required=True,
|
||||
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Ej: iPhone 15 Pro Max'})
|
||||
)
|
||||
briefdesc = forms.CharField(
|
||||
label="Descripción Breve",
|
||||
max_length=250,
|
||||
required=True,
|
||||
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Una descripción corta'})
|
||||
)
|
||||
description = forms.CharField(
|
||||
widget=forms.Textarea(attrs={"rows": "5", "class": "form-control"}),
|
||||
max_length=5000,
|
||||
label="Descripción completa",
|
||||
required=True
|
||||
)
|
||||
price = forms.FloatField(
|
||||
label="Precio (en €)",
|
||||
required=True,
|
||||
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': '15.99'})
|
||||
)
|
||||
stock = forms.IntegerField(
|
||||
label="Stock Disponible",
|
||||
required=True,
|
||||
widget=forms.TextInput(attrs={'class': 'form-control'})
|
||||
)
|
||||
category = forms.ModelChoiceField(
|
||||
queryset=Category.objects.all(),
|
||||
label="Categoría",
|
||||
required=True,
|
||||
widget=forms.Select(attrs={'class': 'form-control'})
|
||||
)
|
||||
primary_image = forms.ImageField(
|
||||
label="Imagen Principal (opcional)",
|
||||
required=False,
|
||||
widget=forms.ClearableFileInput(attrs={'class': 'form-control', 'accept': 'image/*'})
|
||||
)
|
||||
|
||||
|
||||
class SecondaryImageForm(forms.Form):
|
||||
image = forms.ImageField(
|
||||
label="Seleccionar Imagen",
|
||||
required = True,
|
||||
widget = forms.ClearableFileInput(
|
||||
attrs = {
|
||||
'class': 'form-control',
|
||||
'accept': 'image/*'
|
||||
}
|
||||
)
|
||||
)
|
||||
alt = forms.CharField(
|
||||
label="Texto Alternativo",
|
||||
max_length=255,
|
||||
required = False,
|
||||
widget = forms.TextInput(
|
||||
attrs = {
|
||||
'class': 'form-control',
|
||||
'placeholder': 'Descripción opcional de la imagen'
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class UserLoginForm(forms.Form):
|
||||
email = forms.EmailField(
|
||||
label = "Correo Electrónico",
|
||||
max_length=255,
|
||||
required = True,
|
||||
widget = forms.TextInput(
|
||||
attrs = {
|
||||
'class': 'form-control',
|
||||
'placeholder': 'Correo Electronico de tu cuenta...'
|
||||
}
|
||||
)
|
||||
)
|
||||
password = forms.CharField(
|
||||
label="Contraseña",
|
||||
max_length = 255,
|
||||
required = True,
|
||||
widget = forms.PasswordInput(
|
||||
attrs = {
|
||||
'class': 'form-control',
|
||||
'placeholder': 'Contraseña del usuario'
|
||||
}
|
||||
)
|
||||
)
|
||||
remember = forms.BooleanField(
|
||||
required = False,
|
||||
label = "Recuerdame",
|
||||
widget = forms.CheckboxInput(attrs={'class': 'form-check-input'})
|
||||
)
|
||||
|
||||
|
||||
class UserRegisterForm(forms.Form):
|
||||
name = forms.CharField(
|
||||
label = "Nombre Completo",
|
||||
max_length = 255,
|
||||
required = True,
|
||||
widget = forms.TextInput(
|
||||
attrs = {
|
||||
'class': 'form-control'
|
||||
}
|
||||
)
|
||||
)
|
||||
email = forms.EmailField(
|
||||
label = "Correo Electrónico",
|
||||
max_length = 255,
|
||||
required = True,
|
||||
widget = forms.TextInput(
|
||||
attrs = {
|
||||
'class': 'form-control'
|
||||
}
|
||||
)
|
||||
)
|
||||
password = forms.CharField(
|
||||
label = "Contraseña",
|
||||
max_length = 255,
|
||||
required = True,
|
||||
widget = forms.PasswordInput(
|
||||
attrs = {
|
||||
'class': 'form-control'
|
||||
}
|
||||
)
|
||||
)
|
||||
password_confirm = forms.CharField(
|
||||
label = "Verificar Contraseña",
|
||||
max_length = 255,
|
||||
required = True,
|
||||
widget = forms.PasswordInput(
|
||||
attrs = {
|
||||
'class': 'form-control'
|
||||
}
|
||||
)
|
||||
)
|
||||
terms = forms.BooleanField(
|
||||
required = True,
|
||||
label = "Acepto los terminos y condiciones",
|
||||
widget = forms.CheckboxInput(attrs={'class': 'form-check-input'})
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
password = cleaned_data.get("password")
|
||||
password_confirm = cleaned_data.get("password_confirm")
|
||||
if password and password_confirm and password != password_confirm:
|
||||
raise ValidationError("Las contraseñas no coinciden.")
|
||||
|
||||
|
||||
class EditProfileForm(forms.Form):
|
||||
first_name = forms.CharField(
|
||||
label="Nombre",
|
||||
max_length=150,
|
||||
required=True,
|
||||
widget=forms.TextInput(attrs={'class': 'form-control'})
|
||||
)
|
||||
last_name = forms.CharField(
|
||||
label="Apellidos",
|
||||
max_length=150,
|
||||
required=False,
|
||||
widget=forms.TextInput(attrs={'class': 'form-control'})
|
||||
)
|
||||
email = forms.EmailField(
|
||||
label="Correo Electrónico",
|
||||
max_length=254,
|
||||
required=True,
|
||||
widget=forms.EmailInput(attrs={'class': 'form-control'})
|
||||
)
|
||||
|
||||
|
||||
class ChangePasswordForm(forms.Form):
|
||||
current_password = forms.CharField(
|
||||
label="Contraseña Actual",
|
||||
max_length=128,
|
||||
required=True,
|
||||
widget=forms.PasswordInput(attrs={'class': 'form-control'})
|
||||
)
|
||||
new_password = forms.CharField(
|
||||
label="Nueva Contraseña",
|
||||
max_length=128,
|
||||
required=True,
|
||||
widget=forms.PasswordInput(attrs={'class': 'form-control'})
|
||||
)
|
||||
confirm_password = forms.CharField(
|
||||
label="Confirmar Nueva Contraseña",
|
||||
max_length=128,
|
||||
required=True,
|
||||
widget=forms.PasswordInput(attrs={'class': 'form-control'})
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
new_password = cleaned_data.get("new_password")
|
||||
confirm_password = cleaned_data.get("confirm_password")
|
||||
if new_password and confirm_password and new_password != confirm_password:
|
||||
raise ValidationError("Las contraseñas no coinciden.")
|
||||
if new_password and len(new_password) < 8:
|
||||
raise ValidationError("La contraseña debe tener al menos 8 caracteres.")
|
||||
|
||||
|
||||
class ShippingAddressForm(forms.Form):
|
||||
full_name = forms.CharField(
|
||||
label="Nombre Completo",
|
||||
max_length=255,
|
||||
required=True,
|
||||
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Juan Pérez García'})
|
||||
)
|
||||
address_line_1 = forms.CharField(
|
||||
label="Dirección",
|
||||
max_length=255,
|
||||
required=True,
|
||||
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Calle Mayor 123'})
|
||||
)
|
||||
address_line_2 = forms.CharField(
|
||||
label="Dirección (línea 2)",
|
||||
max_length=255,
|
||||
required=False,
|
||||
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Piso, puerta, etc.'})
|
||||
)
|
||||
city = forms.CharField(
|
||||
label="Población",
|
||||
max_length=100,
|
||||
required=True,
|
||||
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Almería'})
|
||||
)
|
||||
postal_code = forms.CharField(
|
||||
label="Código Postal",
|
||||
max_length=5,
|
||||
required=True,
|
||||
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': '04001'})
|
||||
)
|
||||
country = forms.CharField(
|
||||
label="País",
|
||||
max_length=100,
|
||||
required=False,
|
||||
initial="España",
|
||||
widget=forms.TextInput(attrs={'class': 'form-control', 'readonly': True})
|
||||
)
|
||||
phone = forms.CharField(
|
||||
label="Teléfono",
|
||||
max_length=20,
|
||||
required=True,
|
||||
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': '612 345 678'})
|
||||
)
|
||||
is_default = forms.BooleanField(
|
||||
label="Establecer como dirección predeterminada",
|
||||
required=False,
|
||||
widget=forms.CheckboxInput(attrs={'class': 'form-check-input'})
|
||||
)
|
||||
|
||||
|
||||
class ResetPasswordForm(forms.Form):
|
||||
email = forms.EmailField(
|
||||
label="Correo Electrónico",
|
||||
max_length=254,
|
||||
required=True,
|
||||
widget=forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'tu@email.com'})
|
||||
)
|
||||
|
||||
|
||||
class ResetPasswordPhase2Form(forms.Form):
|
||||
password = forms.CharField(
|
||||
label="Nueva Contraseña",
|
||||
max_length=128,
|
||||
required=True,
|
||||
widget=forms.PasswordInput(attrs={'class': 'form-control'})
|
||||
)
|
||||
verify_password = forms.CharField(
|
||||
label="Confirmar Contraseña",
|
||||
max_length=128,
|
||||
required=True,
|
||||
widget=forms.PasswordInput(attrs={'class': 'form-control'})
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
password = cleaned_data.get("password")
|
||||
verify_password = cleaned_data.get("verify_password")
|
||||
if password and verify_password and password != verify_password:
|
||||
raise ValidationError("Las contraseñas no coinciden.")
|
||||
Reference in New Issue
Block a user