Bu darsda siz Django Forms bilan ishlashni o'rganasiz. User input qabul qilish, validatsiya, formalarni render qilish va ma'lumotlarni qayta ishlashni chuqur o'zlashtirasiz.
Dars oxirida siz:
- ✅ Django Forms nima ekanligini va afzalliklarini tushunasiz
- ✅ Form class yaratishni bilasiz
- ✅ ModelForm dan foydalanishni o'rganasiz
- ✅ Form validation (clean methods) ni bilasiz
- ✅ Template'da formalarni render qilishni o'rganasiz
- ✅ Form errors bilan ishlashni bilasiz
- ✅ Custom widgets va field'lar yaratishni o'rganasiz
- ✅ File upload formalarini yaratishni bilasiz
- Django Views
- Django Templates
- Django Models
- HTML Forms asoslari
- HTTP POST/GET
# forms.py fayl yarating
# app/forms.pyDjango Forms - user input qabul qilish va validatsiya qilish uchun kuchli vosita.
| Afzallik | Tavsif |
|---|---|
| Avtomatik HTML yaratish | Form fields → HTML input |
| Validation | Built-in va custom validation |
| Security | CSRF protection |
| Error handling | Automatic error messages |
| Reusability | Bir form ko'p joyda |
| Form | ModelForm |
|---|---|
| Oddiy form (model'siz) | Model'ga bog'langan form |
| Login, Contact forms | Create/Update model obyektlari |
| Manual field definition | Auto-generated from model |
blog/forms.py:
from django import forms
class ContactForm(forms.Form):
"""
Aloqa formasi
Django form - forms.Form dan meros oladi
Har bir field = form input
"""
# CharField - text input
name = forms.CharField(
max_length=100,
label="Ismingiz", # Label text
help_text="To'liq ismingizni kiriting", # Yordam matni
required=True, # Majburiy
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'John Doe'
})
)
# EmailField - email input va validation
email = forms.EmailField(
label="Email",
required=True,
widget=forms.EmailInput(attrs={
'class': 'form-control',
'placeholder': 'john@example.com'
})
)
# CharField with Textarea widget
message = forms.CharField(
label="Xabar",
required=True,
widget=forms.Textarea(attrs={
'class': 'form-control',
'rows': 5,
'placeholder': 'Xabaringizni yozing...'
})
)
# ChoiceField - dropdown select
subject = forms.ChoiceField(
label="Mavzu",
choices=[
('general', 'Umumiy savol'),
('support', 'Texnik yordam'),
('feedback', 'Fikr-mulohaza'),
],
widget=forms.Select(attrs={
'class': 'form-control'
})
)
# BooleanField - checkbox
agree = forms.BooleanField(
label="Shartlarni qabul qilaman",
required=True
)| Field Type | HTML Input | Validation |
|---|---|---|
| CharField | <input type="text"> |
max_length, min_length |
| EmailField | <input type="email"> |
Email format |
| URLField | <input type="url"> |
URL format |
| IntegerField | <input type="number"> |
Integer |
| DecimalField | <input type="number"> |
Decimal |
| BooleanField | <input type="checkbox"> |
True/False |
| DateField | <input type="date"> |
Date format |
| DateTimeField | <input type="datetime"> |
DateTime format |
| ChoiceField | <select> |
Choices |
| FileField | <input type="file"> |
File upload |
| ImageField | <input type="file"> |
Image file |
blog/views.py:
from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import ContactForm
def contact_view(request):
"""
Contact form view
GET - bo'sh forma ko'rsatish
POST - forma submit bo'lganda
"""
if request.method == 'POST':
# POST data bilan form yaratish
form = ContactForm(request.POST)
# Validatsiya
if form.is_valid():
# Validatsiyadan o'tgan ma'lumotlar
name = form.cleaned_data['name']
email = form.cleaned_data['email']
message = form.cleaned_data['message']
subject = form.cleaned_data['subject']
# Ma'lumotlarni qayta ishlash
# Masalan: email yuborish, database'ga saqlash
# Success message
messages.success(request, 'Xabaringiz muvaffaqiyatli yuborildi!')
# Redirect (PRG pattern - Post-Redirect-Get)
return redirect('blog:contact')
else:
# GET - bo'sh forma
form = ContactForm()
context = {'form': form}
return render(request, 'blog/contact.html', context)blog/templates/blog/contact.html:
{% extends 'base.html' %}
{% block content %}
<div class="container">
<h2>Biz bilan bog'lanish</h2>
<form method="POST" novalidate>
{% csrf_token %}
<!-- 1. Barcha formani bir vaqtda -->
{{ form.as_p }}
<!-- yoki -->
<!-- 2. Har bir field alohida (ko'proq control) -->
<div class="form-group">
{{ form.name.label_tag }}
{{ form.name }}
{% if form.name.errors %}
<div class="text-danger">
{{ form.name.errors }}
</div>
{% endif %}
{% if form.name.help_text %}
<small class="text-muted">{{ form.name.help_text }}</small>
{% endif %}
</div>
<div class="form-group">
{{ form.email.label_tag }}
{{ form.email }}
{% if form.email.errors %}
<div class="text-danger">{{ form.email.errors }}</div>
{% endif %}
</div>
<div class="form-group">
{{ form.message.label_tag }}
{{ form.message }}
{% if form.message.errors %}
<div class="text-danger">{{ form.message.errors }}</div>
{% endif %}
</div>
<div class="form-group">
{{ form.subject.label_tag }}
{{ form.subject }}
</div>
<div class="form-check">
{{ form.agree }}
{{ form.agree.label_tag }}
</div>
<button type="submit" class="btn btn-primary">Yuborish</button>
</form>
</div>
{% endblock %}<!-- As paragraph -->
{{ form.as_p }}
<!-- As table -->
<table>{{ form.as_table }}</table>
<!-- As unordered list -->
<ul>{{ form.as_ul }}</ul>
<!-- Manual rendering -->
{% for field in form %}
<div class="form-group">
{{ field.label_tag }}
{{ field }}
{{ field.errors }}
</div>
{% endfor %}blog/forms.py:
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
"""
Post modeli uchun form
ModelForm - model'dan avtomatik form yaratadi
"""
class Meta:
model = Post # Qaysi model
fields = '__all__' # Barcha maydonlar
# yoki
# fields = ['title', 'content', 'category'] # Aniq maydonlar
# exclude = ['author', 'created_at'] # Bunlardan tashqari
# Labels
labels = {
'title': 'Sarlavha',
'content': 'Mazmun',
'is_published': 'Nashr qilinganmi?',
}
# Help text
help_texts = {
'title': 'Maqola sarlavhasi (maksimal 200 belgi)',
'content': 'Maqola to\'liq mazmuni',
}
# Error messages
error_messages = {
'title': {
'required': 'Sarlavha kiritish shart!',
'max_length': 'Sarlavha juda uzun!',
},
}
# Widgets
widgets = {
'title': forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Maqola sarlavhasi'
}),
'content': forms.Textarea(attrs={
'class': 'form-control',
'rows': 10
}),
'category': forms.Select(attrs={
'class': 'form-control'
}),
}blog/views.py:
from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import PostForm
from .models import Post
def post_create_view(request):
"""
Yangi post yaratish
"""
if request.method == 'POST':
form = PostForm(request.POST, request.FILES) # FILES - rasm uchun
if form.is_valid():
# Formadan model obyekt yaratish
post = form.save(commit=False) # Hali database'ga saqlamaydi
# Qo'shimcha ma'lumotlar qo'shish
post.author = request.user
post.slug = slugify(post.title)
# Database'ga saqlash
post.save()
# Many-to-Many maydonlarni saqlash (agar commit=False bo'lsa)
form.save_m2m()
messages.success(request, 'Maqola muvaffaqiyatli yaratildi!')
return redirect('blog:post_detail', post_id=post.id)
else:
form = PostForm()
context = {'form': form}
return render(request, 'blog/post_create.html', context)blog/views.py:
from django.shortcuts import render, redirect, get_object_or_404
from .forms import PostForm
from .models import Post
def post_update_view(request, post_id):
"""
Mavjud postni yangilash
"""
# Obyektni olish
post = get_object_or_404(Post, id=post_id)
if request.method == 'POST':
# Mavjud obyekt bilan form yaratish
form = PostForm(request.POST, request.FILES, instance=post)
if form.is_valid():
form.save() # Obyektni yangilaydi
messages.success(request, 'Maqola yangilandi!')
return redirect('blog:post_detail', post_id=post.id)
else:
# Mavjud ma'lumotlar bilan form
form = PostForm(instance=post)
context = {
'form': form,
'post': post
}
return render(request, 'blog/post_update.html', context)from django import forms
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'content']
def clean_title(self):
"""
Title maydon uchun validation
clean_<field_name> metod yaratish
"""
title = self.cleaned_data.get('title')
# Validation: Title kamida 10 belgi
if len(title) < 10:
raise forms.ValidationError(
'Sarlavha kamida 10 belgidan iborat bo\'lishi kerak!'
)
# Validation: Title unique bo'lishi kerak
if Post.objects.filter(title=title).exists():
raise forms.ValidationError(
'Bunday sarlavhali maqola allaqachon mavjud!'
)
# Validation: Bad words check
bad_words = ['spam', 'fake']
if any(word in title.lower() for word in bad_words):
raise forms.ValidationError(
'Sarlavhada noto\'g\'ri so\'zlar mavjud!'
)
return titleclass RegistrationForm(forms.Form):
username = forms.CharField(max_length=50)
email = forms.EmailField()
password1 = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(widget=forms.PasswordInput)
def clean(self):
"""
Form-level validation
Bir nechta maydonlarni birga tekshirish
"""
cleaned_data = super().clean()
password1 = cleaned_data.get('password1')
password2 = cleaned_data.get('password2')
# Parollar bir xil bo'lishi kerak
if password1 and password2:
if password1 != password2:
raise forms.ValidationError(
'Parollar bir xil emas!'
)
# Parol kuchli bo'lishi kerak
if len(password1) < 8:
raise forms.ValidationError(
'Parol kamida 8 belgidan iborat bo\'lishi kerak!'
)
return cleaned_datafrom django.core.exceptions import ValidationError
def validate_even_number(value):
"""
Juft son validation
"""
if value % 2 != 0:
raise ValidationError(
f'{value} juft son emas!',
params={'value': value}
)
class MyForm(forms.Form):
# Validator'ni field'ga qo'shish
number = forms.IntegerField(
validators=[validate_even_number]
)from django import forms
class MyForm(forms.Form):
# TextInput
name = forms.CharField(widget=forms.TextInput)
# Textarea
bio = forms.CharField(widget=forms.Textarea)
# PasswordInput
password = forms.CharField(widget=forms.PasswordInput)
# EmailInput
email = forms.EmailField(widget=forms.EmailInput)
# URLInput
website = forms.URLField(widget=forms.URLInput)
# NumberInput
age = forms.IntegerField(widget=forms.NumberInput)
# DateInput
birth_date = forms.DateField(widget=forms.DateInput)
# TimeInput
time = forms.TimeField(widget=forms.TimeInput)
# Select
country = forms.ChoiceField(
choices=[('uz', 'Uzbekistan'), ('us', 'USA')],
widget=forms.Select
)
# RadioSelect
gender = forms.ChoiceField(
choices=[('m', 'Male'), ('f', 'Female')],
widget=forms.RadioSelect
)
# CheckboxInput
agree = forms.BooleanField(widget=forms.CheckboxInput)
# CheckboxSelectMultiple
interests = forms.MultipleChoiceField(
choices=[('tech', 'Technology'), ('sport', 'Sport')],
widget=forms.CheckboxSelectMultiple
)
# FileInput
document = forms.FileField(widget=forms.FileInput)
# ClearableFileInput
image = forms.ImageField(widget=forms.ClearableFileInput)
# HiddenInput
hidden_field = forms.CharField(widget=forms.HiddenInput)class ContactForm(forms.Form):
name = forms.CharField(
widget=forms.TextInput(attrs={
'class': 'form-control',
'id': 'name-field',
'placeholder': 'Ismingizni kiriting',
'autocomplete': 'name',
'required': True,
'autofocus': True,
'maxlength': 100,
})
)
email = forms.EmailField(
widget=forms.EmailInput(attrs={
'class': 'form-control',
'placeholder': 'email@example.com',
})
)
message = forms.CharField(
widget=forms.Textarea(attrs={
'class': 'form-control',
'rows': 5,
'cols': 40,
'placeholder': 'Xabaringiz...',
})
)blog/forms.py:
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'content', 'image']
widgets = {
'image': forms.FileInput(attrs={
'class': 'form-control',
'accept': 'image/*' # Faqat rasmlar
})
}blog/views.py:
def post_create_view(request):
if request.method == 'POST':
# MUHIM: request.FILES ham kerak!
form = PostForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('blog:post_list')
else:
form = PostForm()
return render(request, 'blog/post_create.html', {'form': form})Template:
<!-- MUHIM: enctype="multipart/form-data" -->
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Yuborish</button>
</form>class MultipleFileForm(forms.Form):
files = forms.FileField(
widget=forms.ClearableFileInput(attrs={
'multiple': True,
'class': 'form-control'
})
)
# View
def upload_files(request):
if request.method == 'POST':
form = MultipleFileForm(request.POST, request.FILES)
if form.is_valid():
files = request.FILES.getlist('files')
for file in files:
# Har bir faylni saqlash
pass
else:
form = MultipleFileForm()
return render(request, 'upload.html', {'form': form})Vazifalar:
- ContactForm yarating (name, email, subject, message)
- View yarating (GET va POST)
- Template yarating
- Email yuborish (print qiling)
- Success message
Vazifalar:
- PostForm (ModelForm)
- Create va Update views
- Field validation (title min 10 chars)
- Image upload
- Category select
- CSRF protection
Vazifalar:
- RegistrationForm (username, email, password1, password2)
- Custom validation (password match, username unique)
- Profile picture upload
- Terms checkbox
- Email confirmation
- Custom error messages
# ========== FORM CLASS ==========
from django import forms
class MyForm(forms.Form):
name = forms.CharField(max_length=100)
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea)
# ========== MODELFORM ==========
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = '__all__'
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'})
}
# ========== VIEW ==========
def my_view(request):
if request.method == 'POST':
form = MyForm(request.POST, request.FILES)
if form.is_valid():
data = form.cleaned_data
# Process data
return redirect('success')
else:
form = MyForm()
return render(request, 'form.html', {'form': form})
# ========== TEMPLATE ==========
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
# ========== VALIDATION ==========
def clean_field_name(self):
data = self.cleaned_data['field_name']
if condition:
raise forms.ValidationError("Error message")
return data© 2024 Deepcode Academy. Barcha huquqlar himoyalangan.