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
- 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])
- Initial Data
form = ProductForm(
initial={
'name': 'Produk Baru',
'price': '0.00'
}
)
- 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')