Skip to main content

Overview

The Proyecto system uses Django’s ModelForm framework to handle form rendering, validation, and data processing. All forms are defined in CTP/forms.py and inherit from forms.ModelForm, providing automatic form generation from Django models with customizable widgets and validation. Location: CTP/forms.py

Form Classes

ProjectForm

ModelForm for creating and editing projects (Proyectos). Location: CTP/forms.py:27
class ProjectForm(forms.ModelForm):
    class Meta:
        model = Proyectos
        fields = ['nombre_proyecto', 'lider','encargados']
        widgets = {
            'nombre_proyecto': forms.TextInput(attrs={'class': 'form-control'}),
            'lider': forms.Select(attrs={'class': 'form-control'}),
            'encargados': forms.SelectMultiple(attrs={'class': 'form_control select2'}),
        }
        labels = {'nombre_proyecto': 'nombre_proyecto', 'lider': 'lider', 'encargados':'encargados' }

Meta Configuration

model
Model
default:"Proyectos"
The Django model this form is based on
fields
list
default:"['nombre_proyecto', 'lider', 'encargados']"
List of model fields to include in the form

Fields

nombre_proyecto
CharField
Widget: TextInput with CSS class form-controlLabel: “nombre_proyecto”Description: Project name field. Must be unique per validation in viewProyectos.HTML Attributes:
{'class': 'form-control'}
lider
ForeignKey
Widget: Select with CSS class form-controlLabel: “lider”Description: Project leader selection. References the encargado model as a foreign key.HTML Attributes:
{'class': 'form-control'}
encargados
ManyToManyField
Widget: SelectMultiple with CSS classes form_control select2Label: “encargados”Description: Multiple team member selection. Uses Select2 JavaScript library for enhanced multi-select functionality.HTML Attributes:
{'class': 'form_control select2'}
The select2 class enables the Select2 jQuery plugin for searchable dropdown with multiple selections.

Usage Example

# Creating a new project form
form = ProjectForm()

# Form with POST data
form = ProjectForm(request.POST)
if form.is_valid():
    proyecto = Proyectos(
        nombre_proyecto=form.cleaned_data['nombre_proyecto'],
        lider=form.cleaned_data['lider']
    )
    proyecto.save()
    encargados = form.cleaned_data['encargados']
    proyecto.encargados.set(encargados)

# Editing existing project
proyecto = Proyectos.objects.get(id=id)
form = ProjectForm(request.POST, instance=proyecto)
if form.is_valid():
    form.save()

TareasForm

ModelForm for creating and editing tasks (Tareas). Location: CTP/forms.py:17
class TareasForm(forms.ModelForm):
    class Meta:
        model = Tareas
        fields = ['nombre_tarea', 'encargados']
        widgets = {
            'nombre_tarea': forms.TextInput(attrs={'class': 'form-control'}),
            'encargados': forms.Select(attrs={'class': 'form-control'})
        }
        labels = {'nombre_tarea': 'nombre_tarea', 'encargados': 'lider'}

Meta Configuration

model
Model
default:"Tareas"
The Django model this form is based on
fields
list
default:"['nombre_tarea', 'encargados']"
List of model fields to include in the form

Fields

nombre_tarea
CharField
Widget: TextInput with CSS class form-controlLabel: “nombre_tarea”Description: Task name field. Must be unique per validation in viewTareas.HTML Attributes:
{'class': 'form-control'}
encargados
ForeignKey
Widget: Select with CSS class form-controlLabel: “lider” (note: label differs from field name)Description: Team member assigned to the task. References the encargado model as a foreign key.HTML Attributes:
{'class': 'form-control'}
The label is set to “lider” while the field name is “encargados”, which may cause confusion. This appears to be a naming inconsistency in the original code.

Usage Example

# Creating a new task form
form = TareasForm()

# Form with POST data
form = TareasForm(request.POST)
if form.is_valid():
    tareas = Tareas(
        nombre_tarea=form.cleaned_data['nombre_tarea'],
        encargados=form.cleaned_data['encargados']
    )
    tareas.save(request)

# Editing existing task
tareas = Tareas.objects.get(id=id)
form = TareasForm(request.POST, instance=tareas)
if form.is_valid():
    form.save()

trabajadoresForm

ModelForm for creating and editing team members (encargado). Location: CTP/forms.py:7
class trabajadoresForm(forms.ModelForm):
    class Meta:
        model = encargado
        fields = ['nombres']
        widgets = {
            'nombres': forms.TextInput(attrs={'class': 'form-control',
                                             "placeholder": 'Ingresa el nombre'}), }
        labels = {'nombres': 'nombres'}

Meta Configuration

model
Model
default:"encargado"
The Django model this form is based on
fields
list
default:"['nombres']"
List of model fields to include in the form (single field)

Fields

nombres
CharField
Widget: TextInput with CSS class form-control and placeholderLabel: “nombres”Description: Team member name field. Must be unique per validation in viewtrabajadores.HTML Attributes:
{
    'class': 'form-control',
    'placeholder': 'Ingresa el nombre'
}
Placeholder: “Ingresa el nombre” (Spanish: “Enter the name”)

Usage Example

# Creating a new team member form
form = trabajadoresForm()

# Form with POST data
form = trabajadoresForm(request.POST)
if form.is_valid():
    Encargado = encargado(nombres=form.cleaned_data['nombres'])
    Encargado.save(request)

# Editing existing team member
Encargado = encargado.objects.get(id=id)
form = trabajadoresForm(request.POST, instance=Encargado)
if form.is_valid():
    form.save()

encargadoform

ModelForm for selecting team members (encargados) from projects. Location: CTP/forms.py:38
class encargadoform(forms.ModelForm):
    class Meta:
        model = Proyectos
        fields = ['encargados']
        widgets = {
            'encargados': forms.Select(attrs={'class': 'form-control'})
        }
        labels = {'encargados': 'encargados'}

Meta Configuration

model
Model
default:"Proyectos"
The Django model this form is based on (uses Proyectos model)
fields
list
default:"['encargados']"
List of model fields to include in the form (single field)

Fields

encargados
ManyToManyField
Widget: Select (single selection from many-to-many relationship)Label: “encargados”Description: Single team member selection from project’s assigned team members.HTML Attributes:
{'class': 'form-control'}
Despite being a ManyToManyField in the model, this form uses a Select widget (not SelectMultiple), limiting selection to a single team member.

Usage Example

# Creating a form to select an encargado
form = encargadoform()

# Rendering in template
{{ form.encargados }}

Form Architecture

Base Class

All forms inherit from django.forms.ModelForm, which provides:
  • Automatic form field generation from model fields
  • Built-in validation based on model field constraints
  • Easy integration with Django’s ORM
  • Automatic form rendering in templates

Widget System

Forms use Django’s widget system to control HTML rendering:
TextInput
widget
Renders as <input type="text"> HTML elementCommon Usage: Text fields, names, titles
Select
widget
Renders as <select> HTML dropdown elementCommon Usage: Foreign key relationships, single choice fields
SelectMultiple
widget
Renders as <select multiple> HTML elementCommon Usage: Many-to-many relationships, multiple choice fields

CSS Framework Integration

All forms use Bootstrap CSS classes for styling:
attrs={'class': 'form-control'}
The form-control class is from Bootstrap and provides consistent styling across all form inputs. Some forms also use select2 for enhanced JavaScript functionality.

Form Validation

Automatic Validation

ModelForms automatically validate based on model constraints:
if form.is_valid():
    # Form data is valid
    form.save()
else:
    # Form has errors
    print(form.errors)

Custom Validation

Views implement additional validation logic: Duplicate Checking:
# ProjectForm - view_proyectos.py:23
if Proyectos.objects.filter(nombre_proyecto=request.POST['nombre_proyecto']).exists():
    messages.error(request, 'El nombre está repetido')
    return redirect('{}?action=agregar'.format(request.path))

# TareasForm - view_registros.py:24
if Tareas.objects.filter(nombre_tarea=request.POST['nombre_tarea']).exists():
    messages.error(request, 'El nombre está repetido')
    return redirect('{}?action=agregar'.format(request.path))

# trabajadoresForm - view_trabajadores.py:24
if encargado.objects.filter(nombres=request.POST['nombres']).exists():
    messages.error(request, 'Registro ya existe')
    return redirect('{}?action=agregar'.format(request.path))

Form Rendering

Template Usage

Forms can be rendered in templates using various methods: Full Form:
{{ form.as_p }}
Individual Fields:
{{ form.nombre_proyecto }}
{{ form.lider }}
{{ form.encargados }}
With Labels:
<label>{{ form.nombre_proyecto.label }}</label>
{{ form.nombre_proyecto }}

JavaScript Integration

Forms integrate with JavaScript libraries:
select2
JavaScript Library
Enhanced multi-select dropdowns with search functionalityUsage: Applied to ProjectForm.encargados field via CSS class
'encargados': forms.SelectMultiple(attrs={'class': 'form_control select2'})

Dependencies

from django import forms
from CTP.models import Tareas, encargado, Proyectos
from django.contrib.auth.forms import UserCreationForm
UserCreationForm is imported but not used in the current implementation. This may be for future authentication features.

Best Practices

Form Initialization

Empty Form (Add Action):
form = ProjectForm()
Form with Data (POST):
form = ProjectForm(request.POST)
Form with Instance (Edit Action):
proyecto = Proyectos.objects.get(id=id)
form = ProjectForm(request.POST, instance=proyecto)
Form with Initial Data:
form = ProjectForm(initial=model_to_dict(proyecto))

Error Handling

Always check form validity before saving:
form = ProjectForm(request.POST)
if form.is_valid():
    form.save()
    messages.success(request, 'Saved successfully')
else:
    messages.error(request, 'Validation failed')

Many-to-Many Relationships

Handle many-to-many fields separately when creating objects:
proyecto = Proyectos(
    nombre_proyecto=form.cleaned_data['nombre_proyecto'],
    lider=form.cleaned_data['lider']
)
proyecto.save()  # Must save first
encargados = form.cleaned_data['encargados']
proyecto.encargados.set(encargados)  # Then set M2M

Build docs developers (and LLMs) love