Django
Forms

Django Forms - Panduan Lengkap

1. Dasar Forms Django

Form Dasar

# forms.py
from django import forms
 
class ProductForm(forms.Form):
    name = fields.CharField(max_length=100)
    price = fields.DecimalField(max_digits=10, decimal_places=2)
    description = fields.TextField(required=False)

ModelForm

# forms.py
from django import forms
from .models import Product
 
class ProductModelForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = ['name', 'price', 'description']
        # atau gunakan fields = '__all__' untuk semua field

2. Tipe Field Form

Text Fields

# Field untuk input teks
name = forms.CharField(
    max_length=100,
    label='Nama Produk',
    help_text='Masukkan nama produk'
)
description = forms.TextField(
    widget=forms.Textarea(attrs={'rows': 4})
)
email = forms.EmailField()

Number Fields

# Field untuk angka
price = forms.DecimalField(
    max_digits=10,
    decimal_places=2,
    min_value=0
)
quantity = forms.IntegerField(min_value=1)
rating = forms.FloatField(min_value=0, max_value=5)

Choice Fields

# Field untuk pilihan
CATEGORY_CHOICES = [
    ('electronics', 'Elektronik'),
    ('clothing', 'Pakaian'),
    ('food', 'Makanan'),
]
 
category = forms.ChoiceField(choices=CATEGORY_CHOICES)
tags = forms.MultipleChoiceField(choices=CATEGORY_CHOICES)

File Fields

# Field untuk file
image = forms.ImageField()
document = forms.FileField()

3. Validasi Form

Validasi di Level Field

class ProductForm(forms.Form):
    name = forms.CharField(
        validators=[MinLengthValidator(3)]
    )
 
    def clean_name(self):
        name = self.cleaned_data['name']
        if name.isdigit():
            raise forms.ValidationError('Nama tidak boleh berupa angka')
        return name

Validasi Form Level

class ProductForm(forms.Form):
    price = forms.DecimalField()
    discount_price = forms.DecimalField()
 
    def clean(self):
        cleaned_data = super().clean()
        price = cleaned_data.get('price')
        discount = cleaned_data.get('discount_price')
 
        if discount >= price:
            raise forms.ValidationError(
                'Harga diskon harus lebih kecil dari harga asli'
            )

4. Widgets

class ProductForm(forms.Form):
    name = forms.CharField(
        widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': 'Masukkan nama produk'
        })
    )
    description = forms.CharField(
        widget=forms.Textarea(attrs={
            'class': 'form-control',
            'rows': 4
        })
    )
    category = forms.ChoiceField(
        choices=CATEGORY_CHOICES,
        widget=forms.Select(attrs={'class': 'form-select'})
    )

5. Penggunaan Form di View

Function Based View

from django.shortcuts import render, redirect
 
def product_create(request):
    if request.method == 'POST':
        form = ProductForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()  # Untuk ModelForm
            return redirect('product_list')
    else:
        form = ProductForm()
 
    return render(request, 'products/create.html', {'form': form})

Class Based View

from django.views.generic.edit import CreateView
from .models import Product
 
class ProductCreateView(CreateView):
    model = Product
    form_class = ProductModelForm
    template_name = 'products/create.html'
    success_url = '/products/'

6. Template Form

Template Dasar

<form method="post" enctype="multipart/form-data">
  {% csrf_token %} {{ form.as_p }}
  <button type="submit">Simpan</button>
</form>

Template Custom

<form method="post" enctype="multipart/form-data">
  {% csrf_token %} {% for field in form %}
  <div class="mb-3">
    {{ field.label_tag }} {{ field }} {% if field.errors %} {% for error in field.errors %}
    <div class="alert alert-danger">{{ error }}</div>
    {% endfor %} {% endif %} {% if field.help_text %}
    <small class="text-muted"> {{ field.help_text }} </small>
    {% endif %}
  </div>
  {% endfor %}
 
  <button type="submit" class="btn btn-primary">Simpan</button>
</form>

7. Form Set

Form Set digunakan untuk menangani multiple form dalam satu halaman.

# forms.py
from django.forms import formset_factory, modelformset_factory
 
# Membuat formset dasar
ProductFormSet = formset_factory(
    ProductForm,
    extra=3,  # Jumlah form kosong
    max_num=5 # Maksimum form
)
 
# Membuat model formset
ProductModelFormSet = modelformset_factory(
    Product,
    fields=['name', 'price'],
    extra=1
)

8. Tips Penggunaan Form

  1. Validasi Custom
from django.core.exceptions import ValidationError
 
def validate_positive(value):
    if value <= 0:
        raise ValidationError('Nilai harus positif')
 
class ProductForm(forms.Form):
    price = forms.DecimalField(validators=[validate_positive])
  1. Initial Data
form = ProductForm(
    initial={
        'name': 'Produk Baru',
        'price': '0.00'
    }
)
  1. Dynamic Choices
class ProductForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['category'].choices = Category.objects.values_list('id', 'name')