Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Signal nima
- 2.2. Model signallari
- 2.3. @receiver dekoratori
- 2.4. Signal argumentlari
- 2.5. Signal foydasi va xavfi
- 2.6. Middleware nima
- 2.7. Middleware tuzilishi
- 2.8. Middleware ishlatilishi
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — post_save signal
- Misol 2 — pre_delete va signal bilan boshqa model
- Misol 3 — Middleware
- Misol 4 — Amaliy: signal va middleware birga
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
21.15-dars: Signal va middleware
21-QISM — DJANGO · 15-dars
1. Kirish va motivatsiya
Django'ning ikki kuchli mexanizmi bor: signal (model hodisalari — model saqlanganda avtomatik amal) va middleware (har so'rov/javobni qayta ishlovchi qatlam). Bular kodni ajratishga yordam beradi: asosiy mantiq bir joyda, yon ta'sir (log, xabar) boshqada — bir-biriga aralashmasdan.
Signal — "hodisaga obuna" (event) tamoyili: model saqlansa (post_save), o'chirilsa (pre_delete) — obuna bo'lgan funksiya avtomatik ishlaydi. Middleware — har so'rov view'ga kirishdan oldin va javob chiqishdan keyin ishlovchi qatlam (autentifikatsiya, log, CORS). Bular Django'ning kengaytiriladigan arxitekturasining asosi.
Real vaziyat. Bir jamoa kurs yaratilganda email yuborish, log yozish, statistika yangilashni har view'da takrorlardi — kurs yaratilgan har joyda shu kod. Ular signal'ga o'tdi: post_save signaliga obuna bo'lgan funksiya — kurs qayerda yaratilsa ham avtomatik ishlaydi. Yana har so'rovni log qilish uchun middleware yozdi (har view'da emas). Kod ajratildi, takror yo'qoldi. Signal/middleware — toza, kengaytiriladigan arxitektura.
Bu darsda signal va middleware'ni — hodisalar va so'rov qatlamini o'rganamiz.
Bu darsda:
- Signal nima (hodisaga obuna)
- Model signallari (
post_save,pre_delete) @receiverdekoratori- Signal argumentlari (
created,instance) - Middleware nima (so'rov qatlami)
- Middleware tuzilishi
- So'rov va javobni qayta ishlash
- Amaliy: signal va middleware
ℹ Misollarda Django signal va middleware bilan sinaladi.
2. Nazariya — chuqur tushuntirish
2.1. Signal nima
Signal — Django'dagi hodisa tizimi (event): biror narsa sodir bo'lsa, obuna bo'lgan funksiya ishlaydi:
Model saqlanadi → post_save signal → obuna funksiya ishlaydi| Element | Ma'no |
|---|---|
| Signal | Hodisa (post_save) |
| Sender | Kim yubordi (model) |
| Receiver | Obuna funksiya |
Signal — "nashr-obuna" (publish-subscribe) naqshi: bir joy hodisani e'lon qiladi (model saqlandi), boshqa joylar unga obuna (avtomatik ishlaydi). Bu asosiy kodni yon ta'sirdan (log, email) ajratadi.
2.2. Model signallari
Django model hodisalari uchun tayyor signallar:
| Signal | Qachon |
|---|---|
pre_save |
Saqlashdan oldin |
post_save |
Saqlashdan keyin |
pre_delete |
O'chirishdan oldin |
post_delete |
O'chirishdan keyin |
m2m_changed |
M2M o'zgarganda |
from django.db.models.signals import post_save
# Kurs saqlanganda ishlaydi Model signallari — model hayoti (saqlash, o'chirish) hodisalari. post_save — eng ko'p ishlatiladi (yaratilgandan keyin: email, log). pre_* — oldin (validatsiya, tayyorgarlik).
2.3. @receiver dekoratori
@receiver — funksiyani signal'ga obuna qiladi:
from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save, sender=Kurs)
def kurs_saqlandi(sender, instance, created, **kwargs):
if created:
print(f"Yangi kurs: {instance.nom}") @receiver(signal, sender=Model) — funksiyani signal'ga bog'laydi. sender — qaysi model (usiz barcha modellar). Funksiya sender, instance (obyekt) va boshqa argumentlarni oladi. Kurs saqlanganda bu funksiya avtomatik ishlaydi.
2.4. Signal argumentlari
Signal receiver'iga argumentlar beriladi:
| Argument | Ma'no |
|---|---|
sender |
Signal yuborgan model |
instance |
Obyekt (saqlangan/o'chirilgan) |
created |
Yangi yaratildi mi (post_save) |
**kwargs |
Qolgan argumentlar |
@receiver(post_save, sender=Kurs)
def handler(sender, instance, created, **kwargs):
if created: # yangi yaratildi
...
else: # yangilandi
... created (post_saveda) — obyekt yangi (True) yoki yangilandi (False). instance — obyektning o'zi (instance.nom). **kwargs — kelajakdagi argumentlar uchun (har doim qo'shing).
2.5. Signal foydasi va xavfi
| Foyda | Xavf |
|---|---|
| Kodni ajratadi | Yashiringan mantiq |
| Takrorni yo'qotadi | Kuzatish qiyin |
| Kengaytiriladigan | Ketma-ketlik noaniq |
Signal — kuchli, lekin ehtiyot: mantiq "yashiringan" (model saqlansa nima bo'lishi kod'da ko'rinmaydi). Oddiy holatda to'g'ridan chaqirish (funksiya()) aniqroq. Signal — ajratilgan yon ta'sir (log, email, boshqa app) uchun.
2.6. Middleware nima
Middleware — har so'rov/javobni qayta ishlovchi qatlam:
So'rov → Middleware 1 → Middleware 2 → View → Middleware 2 → Middleware 1 → JavobMiddleware — so'rov view'ga kirishdan oldin va javob chiqishdan keyin ishlovchi kod. Har so'rov ular orqali o'tadi (autentifikatsiya, log, CORS, xavfsizlik). Bu 20.7 dagi bog'liqlikka o'xshaydi, lekin butun ilova darajasida (har so'rov).
2.7. Middleware tuzilishi
Middleware — chaqiriladigan klass (yoki funksiya):
class LogMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# so'rovdan OLDIN (view'gacha)
javob = self.get_response(request) # keyingi qatlam/view
# javobdan KEYIN
javob["X-Qayta-Ishlangan"] = "ha"
return javob Middleware — __call__(request) metodi: get_response(request)dan oldin (so'rovni qayta ishlash), keyin (javobni qayta ishlash). MIDDLEWARE ro'yxatiga qo'shiladi (tartib muhim). Bu har so'rovga qo'llanadigan umumiy mantiq.
2.8. Middleware ishlatilishi
| Middleware | Vazifa |
|---|---|
| Autentifikatsiya | request.user o'rnatish |
| Sessiya | Sessiya boshqaruvi |
| CORS | Cross-origin sarlavhalar |
| Log | Har so'rovni log |
| Xavfsizlik | CSRF, XSS himoya |
Middleware — butun ilova uchun umumiy mantiq (har so'rov). Django tayyor middleware'lar beradi (auth, sessiya, xavfsizlik). O'z middleware'ingiz (log, maxsus sarlavha) yozish mumkin. Bu 20.7 DI'ning ilova darajasidagi versiyasi.
3. Tez ma'lumotnoma
# SIGNAL:
from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver
@receiver(post_save, sender=Kurs)
def kurs_saqlandi(sender, instance, created, **kwargs):
if created:
Log.objects.create(xabar=f"Yangi: {instance.nom}")
# MIDDLEWARE:
class LogMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# oldin
javob = self.get_response(request)
# keyin
return javob
# settings.py: MIDDLEWARE = [..., "app.middleware.LogMiddleware"]Signallar
pre_save · post_save (created) · pre_delete · post_delete · m2m_changed4. Batafsil misollar
Misollarda Django signal va middleware bilan sinaladi.
Misol 1 — post_save signal
"""post_save signal; @receiver; created (yangi vs yangilandi); instance; avtomatik amal."""
import warnings
warnings.filterwarnings("ignore")
import sys
import tempfile
import types
import django
from django.conf import settings
settings.configure(
DEBUG=False,
DATABASES={"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}},
INSTALLED_APPS=["wisar"],
DEFAULT_AUTO_FIELD="django.db.models.BigAutoField",
)
_app = types.ModuleType("wisar")
_app.__path__ = [tempfile.gettempdir()]
sys.modules["wisar"] = _app
django.setup()
from django.db import connection, models
from django.db.models.signals import post_save
from django.dispatch import receiver
JURNAL: list[str] = []
class Kurs(models.Model):
nom = models.CharField(max_length=100)
class Meta:
app_label = "wisar"
@receiver(post_save, sender=Kurs)
def kurs_saqlandi(sender, instance, created, **kwargs):
holat = "yaratildi" if created else "yangilandi"
JURNAL.append(f"{holat}: {instance.nom}")
def main() -> None:
with connection.schema_editor() as se:
se.create_model(Kurs)
print("=== 1. Yaratish (created=True) ===")
kurs = Kurs.objects.create(nom="Python")
print(f" jurnal: {JURNAL[-1]}")
print("\n=== 2. Yangilash (created=False) ===")
kurs.nom = "Python 3.14"
kurs.save()
print(f" jurnal: {JURNAL[-1]}")
print("\n=== 3. Yana yaratish ===")
Kurs.objects.create(nom="Go")
print(f" jurnal: {JURNAL[-1]}")
print("\n=== 4. Signal avtomatik ishladi ===")
print(f" barcha hodisalar: {JURNAL}")
print(" ⭐ post_save + @receiver — model saqlanganda avtomatik")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Yaratish (created=True) ===
jurnal: yaratildi: Python
=== 2. Yangilash (created=False) ===
jurnal: yangilandi: Python 3.14
=== 3. Yana yaratish ===
jurnal: yaratildi: Go
=== 4. Signal avtomatik ishladi ===
barcha hodisalar: ['yaratildi: Python', 'yangilandi: Python 3.14', 'yaratildi: Go']
⭐ post_save + @receiver — model saqlanganda avtomatikNima ko'rsatdi: 2.1, 2.2, 2.3, 2.4-bo'limlar.
Misol 2 — pre_delete va signal bilan boshqa model
"""pre_delete signal; signal ichida boshqa model yaratish (log); ajratilgan yon ta'sir; ketma-ketlik."""
import warnings
warnings.filterwarnings("ignore")
import sys
import tempfile
import types
import django
from django.conf import settings
settings.configure(
DEBUG=False,
DATABASES={"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}},
INSTALLED_APPS=["wisar"],
DEFAULT_AUTO_FIELD="django.db.models.BigAutoField",
)
_app = types.ModuleType("wisar")
_app.__path__ = [tempfile.gettempdir()]
sys.modules["wisar"] = _app
django.setup()
from django.db import connection, models
from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver
class Kurs(models.Model):
nom = models.CharField(max_length=100)
class Meta:
app_label = "wisar"
class Audit(models.Model):
xabar = models.CharField(max_length=200)
class Meta:
app_label = "wisar"
@receiver(post_save, sender=Kurs)
def kurs_yaratildi(sender, instance, created, **kwargs):
if created:
Audit.objects.create(xabar=f"Kurs yaratildi: {instance.nom}")
@receiver(pre_delete, sender=Kurs)
def kurs_ochirilmoqda(sender, instance, **kwargs):
Audit.objects.create(xabar=f"Kurs o'chirildi: {instance.nom}")
def main() -> None:
for m in (Kurs, Audit):
with connection.schema_editor() as se:
se.create_model(m)
print("=== 1. Yaratish → audit yozuvi ===")
kurs = Kurs.objects.create(nom="Python")
print(f" audit yozuvlari: {Audit.objects.count()}")
print(f" oxirgi: {Audit.objects.last().xabar}")
print("\n=== 2. Yana yaratish ===")
Kurs.objects.create(nom="Go")
print(f" audit: {Audit.objects.count()}")
print("\n=== 3. O'chirish → audit yozuvi ===")
kurs.delete()
print(f" oxirgi audit: {Audit.objects.last().xabar}")
print("\n=== 4. Ajratilgan yon ta'sir ===")
print(f" barcha audit: {list(Audit.objects.values_list('xabar', flat=True))}")
print(" ⭐ signal — asosiy kodni yon ta'sirdan ajratadi (audit)")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Yaratish → audit yozuvi ===
audit yozuvlari: 1
oxirgi: Kurs yaratildi: Python
=== 2. Yana yaratish ===
audit: 2
=== 3. O'chirish → audit yozuvi ===
oxirgi audit: Kurs o'chirildi: Python
=== 4. Ajratilgan yon ta'sir ===
barcha audit: ['Kurs yaratildi: Python', 'Kurs yaratildi: Go', "Kurs o'chirildi: Python"]
⭐ signal — asosiy kodni yon ta'sirdan ajratadi (audit)Nima ko'rsatdi: 2.2, 2.5-bo'limlar.
Misol 3 — Middleware
"""middleware (so'rov qatlami); __call__ (oldin/keyin); request/javobni qayta ishlash; har so'rov."""
import warnings
warnings.filterwarnings("ignore")
import sys
import tempfile
import types
import django
from django.conf import settings
class SorovLogMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# so'rovdan OLDIN
request.META["X_BOSHLANDI"] = "ha"
javob = self.get_response(request)
# javobdan KEYIN
javob["X-Qayta-Ishlangan"] = "middleware"
return javob
settings.configure(
DEBUG=False,
DATABASES={"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}},
INSTALLED_APPS=["wisar"],
ROOT_URLCONF=__name__,
ALLOWED_HOSTS=["*"],
SECRET_KEY="namuna",
MIDDLEWARE=[__name__ + ".SorovLogMiddleware"],
DEFAULT_AUTO_FIELD="django.db.models.BigAutoField",
)
_app = types.ModuleType("wisar")
_app.__path__ = [tempfile.gettempdir()]
sys.modules["wisar"] = _app
django.setup()
from django.http import JsonResponse
from django.urls import path
def view(request):
return JsonResponse({"boshlandi": request.META.get("X_BOSHLANDI")})
urlpatterns = [path("test/", view)]
def main() -> None:
from django.test import Client
client = Client()
print("=== 1. Middleware so'rovni qayta ishladi (oldin) ===")
javob = client.get("/test/")
print(f" view'da X_BOSHLANDI: {javob.json()['boshlandi']}")
print("\n=== 2. Middleware javobni qayta ishladi (keyin) ===")
print(f" javob sarlavhasi X-Qayta-Ishlangan: {javob['X-Qayta-Ishlangan']}")
print("\n=== 3. Har so'rov middleware orqali ===")
javob2 = client.get("/test/")
print(f" ikkinchi so'rov ham: {javob2.json()['boshlandi']}")
print("\n=== 4. So'rov → oldin → view → keyin → javob ===")
print(" middleware har so'rov/javobni o'raydi")
print(" ⭐ middleware — har so'rov/javob qatlami (oldin va keyin)")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Middleware so'rovni qayta ishladi (oldin) ===
view'da X_BOSHLANDI: ha
=== 2. Middleware javobni qayta ishladi (keyin) ===
javob sarlavhasi X-Qayta-Ishlangan: middleware
=== 3. Har so'rov middleware orqali ===
ikkinchi so'rov ham: ha
=== 4. So'rov → oldin → view → keyin → javob ===
middleware har so'rov/javobni o'raydi
⭐ middleware — har so'rov/javob qatlami (oldin va keyin)Nima ko'rsatdi: 2.6, 2.7-bo'limlar.
Misol 4 — Amaliy: signal va middleware birga
Signal (model hodisalari) va middleware (so'rov qatlami) ni birga ishlatami: kurs yaratilganda audit (signal), va har so'rovni log (middleware). Bu — Django kengaytiriladigan arxitekturasining namunasi.
"""signal + middleware birga: kurs audit (signal), so'rov log (middleware); ajratilgan yon ta'sirlar."""
import warnings
warnings.filterwarnings("ignore")
import sys
import tempfile
import types
import django
from django.conf import settings
SO_ROVLAR: list[str] = []
class SorovSanaMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
SO_ROVLAR.append(request.path)
javob = self.get_response(request)
javob["X-So-rov-Soni"] = str(len(SO_ROVLAR))
return javob
settings.configure(
DEBUG=False,
DATABASES={"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}},
INSTALLED_APPS=["wisar"],
ROOT_URLCONF=__name__,
ALLOWED_HOSTS=["*"],
SECRET_KEY="namuna",
MIDDLEWARE=[__name__ + ".SorovSanaMiddleware"],
DEFAULT_AUTO_FIELD="django.db.models.BigAutoField",
)
_app = types.ModuleType("wisar")
_app.__path__ = [tempfile.gettempdir()]
sys.modules["wisar"] = _app
django.setup()
from django.db import connection, models
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.http import JsonResponse
from django.urls import path
AUDIT: list[str] = []
class Kurs(models.Model):
nom = models.CharField(max_length=100)
class Meta:
app_label = "wisar"
@receiver(post_save, sender=Kurs)
def kurs_audit(sender, instance, created, **kwargs):
if created:
AUDIT.append(f"kurs yaratildi: {instance.nom}")
def yarat_view(request):
kurs = Kurs.objects.create(nom=request.GET.get("nom", "Nomsiz"))
return JsonResponse({"yaratildi": kurs.nom})
urlpatterns = [path("yarat/", yarat_view)]
def main() -> None:
with connection.schema_editor() as se:
se.create_model(Kurs)
from django.test import Client
client = Client()
print("=== 1. So'rov (middleware + view + signal) ===")
javob = client.get("/yarat/?nom=Python")
print(f" javob: {javob.json()}")
print("\n=== 2. Signal audit yozdi ===")
print(f" audit: {AUDIT}")
print("\n=== 3. Middleware so'rovni logladi ===")
print(f" so'rovlar: {SO_ROVLAR}")
print(f" javob sarlavha X-So-rov-Soni: {javob['X-So-rov-Soni']}")
print("\n=== 4. Ikkinchi so'rov ===")
client.get("/yarat/?nom=Go")
print(f" audit: {AUDIT}")
print(f" so'rovlar soni: {len(SO_ROVLAR)}")
print(" ⭐ signal (model hodisasi) + middleware (so'rov qatlami) birga")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. So'rov (middleware + view + signal) ===
javob: {'yaratildi': 'Python'}
=== 2. Signal audit yozdi ===
audit: ['kurs yaratildi: Python']
=== 3. Middleware so'rovni logladi ===
so'rovlar: ['/yarat/']
javob sarlavha X-So-rov-Soni: 1
=== 4. Ikkinchi so'rov ===
audit: ['kurs yaratildi: Python', 'kurs yaratildi: Go']
so'rovlar soni: 2
⭐ signal (model hodisasi) + middleware (so'rov qatlami) birgaNima ko'rsatdi: 2.1–2.8-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Yon ta'sirni har view'da" | Signal (avtomatik) |
| "Signal — oddiy chaqiriq" | Hodisaga obuna (event) |
"post_saveda created yo'q" |
Bor (yangi/yangilandi) |
| "Signal doim yaxshi" | Ehtiyot (yashiringan mantiq) |
| "Middleware — bir view" | Har so'rov (butun ilova) |
| "Middleware faqat so'rovni" | So'rov va javob |
"**kwargs keraksiz" |
Har doim qo'shing |
| "Middleware tartibi muhim emas" | Muhim (ketma-ketlik) |
6. Keng tarqalgan xatolar va yechimlari
1. Yon ta'sirni har view'da takrorlash
# har view'da email/log/audit # ⚠️ takror
@receiver(post_save, sender=Kurs) # ✅ signal2. **kwargsni unutish
def handler(sender, instance, created): # ⚠️ kelajakda buziladi
def handler(sender, instance, created, **kwargs): # ✅3. Signal'da og'ir ish
@receiver(post_save, ...)
def handler(...): sekin_hisob() # ⚠️ saqlashni sekinlashtiradi
# ✅ og'ir ish — fon vazifasi (20.14)4. Middleware'da get_response chaqirmaslik
def __call__(self, request):
# javob qaytarmadi # ❌ zanjir uzildi
return self.get_response(request) # ✅5. Signal'ni oddiy chaqiriq o'rniga
# oddiy holatda signal # ⚠️ yashiringan mantiq
funksiya(instance) # ✅ to'g'ridan (aniqroq)6. senderni bermaslik
@receiver(post_save) # ⚠️ barcha model uchun
@receiver(post_save, sender=Kurs) # ✅ faqat Kurs7. Middleware'ni MIDDLEWAREga qo'shmaslik
# middleware yozildi, lekin faol emas # ⚠️
MIDDLEWARE = [..., "app.middleware.LogMiddleware"] # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 21.3-dars (o'tilgan): model — signal manbai
- 20.7-dars (o'tilgan): DI — middleware o'xshashi
- 20.14-dars (o'tilgan): fon vazifalari — signal'da og'ir ish
- 12-qism (o'tilgan): hodisa/observer naqshi
- 21.16-dars: deploy — middleware sozlamalari
8. Eng yaxshi amaliyotlar
Ajratilgan yon ta'sir (audit, email) uchun signal.
@receiver(signal, sender=Model)bilan aniq model.**kwargsni har doim qo'shing.Signal'da og'ir ish qilmang (fon vazifasi).
Oddiy holatda to'g'ridan chaqiriq (signal emas).
Middleware'da
get_responseni chaqiring.Middleware'ni
MIDDLEWAREga qo'shing (tartib muhim).Har so'rovga umumiy mantiq uchun middleware.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # signal nima?
2. # post_save qachon?
3. # @receiver nima?
4. # created nima?
5. # instance nima?
6. # sender nima?
7. # middleware nima?
8. # middleware qachon ishlaydi?
9. # get_response nima?
10. # signal xavfi nima?
11. # **kwargs nega?
12. # signal yoki chaqiriq?Javoblar
- Hodisaga obuna (event) tizimi
- Model saqlangandan keyin
- Funksiyani signal'ga obuna qiladi
- Obyekt yangi (True) yoki yangilandi (False)
- Obyektning o'zi (saqlangan/o'chirilgan)
- Signal yuborgan model
- Har so'rov/javobni qayta ishlovchi qatlam
- So'rov (oldin) va javob (keyin)
- Keyingi qatlam/view'ni chaqiradi
- Yashiringan mantiq (kuzatish qiyin)
- Kelajakdagi argumentlar uchun
- Ajratilgan yon ta'sir → signal; oddiy → chaqiriq
Vazifa 2: Xatolarni tuzating
1. # har view'da audit # signal
2. def handler(sender, instance, created): # kwargs
3. def __call__(self, request):
# javob qaytarmadi # get_response
4. @receiver(post_save) # sender
5. # middleware faol emas # MIDDLEWAREJavoblar
1. @receiver(post_save, sender=Kurs)
2. def handler(sender, instance, created, **kwargs):
3. def __call__(self, request):
return self.get_response(request)
4. @receiver(post_save, sender=Kurs)
5. MIDDLEWARE = [..., "app.middleware.LogMiddleware"]Vazifa 3: Audit signal
Audit tizimi:
post_save,pre_deletesignallari- Har o'zgarishni audit modeliga
createdbilan yaratish/yangilash- Standalone test
Vazifa 4: Profil signal
Foydalanuvchi profili:
Userpost_save(yangi bo'lsa profil yaratish)createdtekshiruvi- Avtomatik profil
- Test
Vazifa 5: Log middleware
So'rov log middleware:
- Har so'rovni log (URL, metod, vaqt)
- Javob sarlavhasi (so'rov ID)
Clientbilan test- Bir necha so'rov
Vazifa 6: Signal va middleware birga
To'liq tizim:
- Model signal (audit)
- Middleware (so'rov log)
- View (model o'zgartiradi)
- Ikkalasi ishlashini test
Vazifa 7: O'ylash
Signal va middleware yon ta'sirni (log, audit, email) asosiy kod'dan ajratadi: view o'z ishini qiladi (kurs yaratadi), signal/middleware yon ta'sirni (audit, log) alohida qiladi. Bu "vazifalarni ajratish" (separation of concerns) tamoyili — har qism bir vazifaga mas'ul. Asosiy mantiqni yon ta'sirdan ajratishning afzalligi nima, va nima uchun signal'ning "yashiringan" tabiati (kod'da ko'rinmaydi) ehtiyotni talab qiladi?
Javob
Qisqa javob: Signal/middleware yon ta'sirni (audit, log, email) asosiy kod'dan ajratadi: view faqat o'z ishini qiladi (kurs yaratadi), yon ta'sir alohida (signal). Afzalligi: toza kod (view yengil, bir vazifa), takrorsiz (yon ta'sir bir joyda, har view'da emas), kengaytiriladigan (yangi yon ta'sir qo'shish — yangi signal, view'ni o'zgartirmasdan). Lekin signal "yashiringan" — kod'ni o'qib, model saqlansa nima bo'lishi ko'rinmaydi (signal boshqa joyda). Bu kuzatishni qiyinlashtiradi (nima uchun audit yozildi? — signal'ni topish kerak). Shuning uchun signal — ajratilgan, mustaqil yon ta'sir uchun (audit, email), oddiy holatda to'g'ridan chaqiriq aniqroq.
1. Vazifalarni ajratish
| Asosiy (view) | Yon ta'sir (signal/middleware) |
|---|---|
| Kurs yaratadi | Audit yozadi |
| So'rovga javob | Log qiladi |
| Bir vazifa | Alohida |
2. Ajratishning afzalligi
| Afzallik | Sabab |
|---|---|
| Toza kod | View yengil |
| Takrorsiz | Yon ta'sir bir joyda |
| Kengaytiriladigan | Yangi signal qo'shish |
| Test | Alohida sinaladi |
3. Signal "yashiringan" tabiati
Signal kod'da ko'rinmaydi: Kurs.objects.create(...) — audit yozilishi shu qatorda ko'rinmaydi (signal boshqa joyda). Bu:
- Kuzatish qiyin (nima bo'ldi?)
- Ketma-ketlik noaniq
- Debug qiyin
4. Qachon signal, qachon chaqiriq
| Signal | To'g'ridan chaqiriq |
|---|---|
| Ajratilgan yon ta'sir | Asosiy mantiq |
| Boshqa app | Shu funksiya |
| Audit, email | Aniq ketma-ketlik |
5. Muhandislik saboqlari
- Yon ta'sirni asosiy kod'dan ajrat (signal)
- Ajratish — toza, takrorsiz, kengaytiriladigan
- Signal yashiringan — ehtiyot (kuzatish qiyin)
- Oddiy holatda to'g'ridan chaqiriq (aniqroq)
6. Xulosa
- Signal/middleware — yon ta'sirni ajratadi
- Ajratish — toza kod, vazifalar bo'lingan
- Signal yashiringan — kuzatish qiyin (ehtiyot)
- Ajratilgan yon ta'sir → signal; oddiy → chaqiriq
Nimani mustahkamlaydi: 2.1–2.8-bo'limlar.
Xulosa
Bu darsda Django signal va middleware'ni o'rgandik.
Eng muhim uch fikr:
Signal — hodisaga obuna. Signal — Django'dagi hodisa (event) tizimi: biror narsa sodir bo'lsa, obuna funksiya avtomatik ishlaydi ("nashr-obuna" naqshi). Model signallari:
post_save(saqlashdan keyin — eng ko'p, email/log/audit uchun),pre_save,pre_delete,post_delete,m2m_changed.@receiver(signal, sender=Model)— funksiyani signal'ga obuna qiladi. Receiver argumentlari:sender(model),instance(obyekt),created(post_saveda — yangi/yangilandi),**kwargs(har doim qo'shing).Middleware — so'rov qatlami. Middleware — har so'rov/javobni qayta ishlovchi qatlam: so'rov view'ga kirishdan oldin va javob chiqishdan keyin ishlaydi.
__call__(request)metodi —get_response(request)dan oldin (so'rov) va keyin (javob).MIDDLEWAREro'yxatiga qo'shiladi (tartib muhim). Butun ilova uchun umumiy mantiq: autentifikatsiya, sessiya, CORS, log, xavfsizlik. Django tayyor middleware'lar beradi; o'z middleware'ingiz ham mumkin.Vazifalarni ajratish. Signal va middleware yon ta'sirni (audit, log, email) asosiy kod'dan ajratadi: view o'z ishini qiladi (kurs yaratadi), signal/middleware yon ta'sirni alohida qiladi — bu "vazifalarni ajratish" (separation of concerns). Afzalligi: toza kod (view yengil), takrorsiz (yon ta'sir bir joyda), kengaytiriladigan. Lekin signal "yashiringan" (kod'da ko'rinmaydi) — kuzatishni qiyinlashtiradi, shuning uchun ehtiyot: signal ajratilgan yon ta'sir uchun, oddiy holatda to'g'ridan chaqiriq aniqroq. Signal'da og'ir ish qilmang (fon vazifasi, 20.14).
Keyingi darsda deploy ni o'rganamiz va 21-qismni yakunlaymiz: Django loyihasini ishlab chiqarishga chiqarish — settings (production), WSGI/ASGI, static fayllar, xavfsizlik va server sozlamalari.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!