Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Serializer maydonlari va fields
- 2.2. Maydon validatsiyasi
- 2.3. Obyekt validatsiyasi
- 2.4. source (maydon manbai)
- 2.5. SerializerMethodField
- 2.6. Nested serializer (bog'langan)
- 2.7. read_only / write_only
- 2.8. Serializer — API shartnomasi
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — fields, source va SerializerMethodField
- Misol 2 — Validatsiya (validate_<maydon>, validate)
- Misol 3 — Nested serializer va read_only/write_only
- Misol 4 — Amaliy: to'liq serializer
- 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.13-dars: Serializer
21-QISM — DJANGO · 13-dars
1. Kirish va motivatsiya
O'tgan darsda serializer'ning asosini (ModelSerializer, .data, save) ko'rdik. Endi uni chuqurroq o'rganamiz: maxsus maydonlar, validatsiya, bog'langan (nested) serializer, hisoblangan maydonlar. Serializer — DRF'ning yuragi: u model va JSON o'rtasidagi butun aloqani boshqaradi — qaysi maydon, qanday format, qanday validatsiya.
Serializer — 20.5 dagi Pydantic modeli va 21.8 dagi ModelFormning DRF versiyasi, lekin API uchun boyitilgan: bog'langan ma'lumot (muallif kurslari), maxsus maydonlar (hisoblangan), moslashuvchan validatsiya. To'g'ri serializer — toza, xavfsiz, moslashuvchan API.
Real vaziyat. Bir jamoa API'da butun modelni (barcha maydon) qaytarardi — parol hash, ichki maydonlar ham JSON'da ko'rindi (xavfsizlik teshigi). Va bog'langan ma'lumot (muallif ismi) uchun mijoz alohida so'rov yuborardi (ko'p so'rov). Ular serializer'ni sozladi: fields bilan faqat kerak maydon, source bilan muallif ismi, nested serializer bilan bog'langan ma'lumot bir javobda. API xavfsiz, samarali, qulay bo'ldi.
Bu darsda serializer'ni — maydonlar, validatsiya, nested va maxsus maydonlarni o'rganamiz.
Bu darsda:
- Serializer maydonlari va
fields - Maydon validatsiyasi (
validate_<maydon>) - Obyekt validatsiyasi (
validate) source(maydon manbai)SerializerMethodField(hisoblangan)- Nested serializer (bog'langan)
read_only/write_only- Amaliy: to'liq serializer
ℹ Misollarda DRF serializer bilan sinaladi.
2. Nazariya — chuqur tushuntirish
2.1. Serializer maydonlari va fields
fields — JSON'da qaysi maydonlar bo'lishini belgilaydi:
class KursSerializer(serializers.ModelSerializer):
class Meta:
model = Kurs
fields = ["id", "nom", "narx"] # faqat shu maydonlar
# yoki exclude = ["maxfiy"]
# yoki fields = "__all__" (hammasi — ehtiyot!) fields — JSON'ga qaysi maydon kirishini aniq belgilaydi. "__all__" (barcha) — ehtiyot (maxfiy maydon ham). Aniq ro'yxat — xavfsiz (faqat kerak). Bu 20.5 dagi response_model (javob filtri) ga o'xshaydi.
2.2. Maydon validatsiyasi
validate_<maydon> — bir maydon uchun maxsus validatsiya:
class KursSerializer(serializers.ModelSerializer):
class Meta:
model = Kurs
fields = ["nom", "narx"]
def validate_narx(self, value):
if value < 0:
raise serializers.ValidationError("narx manfiy bo'lmasin")
return value validate_<maydon> — maydon qiymatini tekshiradi/tozalaydi (raise ValidationError yoki return). Bu 20.5 dagi field_validator, 21.8 dagi clean_<maydon> ga o'xshaydi. Xato serializer.errors[maydon]da.
2.3. Obyekt validatsiyasi
validate — butun obyekt (maydonlar aloqasi):
def validate(self, data):
if data["chegirma"] > data["narx"]:
raise serializers.ValidationError("chegirma narxdan katta")
return data validate — bir necha maydon aloqasi (chegirma < narx). Xato errors["non_field_errors"]da. Bu 21.8 dagi clean() ga o'xshaydi. Maydon (validate_<maydon>) va obyekt (validate) validatsiyasi birga ishlaydi.
2.4. source (maydon manbai)
source — maydon qiymati qaydan olinishini belgilaydi:
class KursSerializer(serializers.ModelSerializer):
muallif_ism = serializers.CharField(source="muallif.ism", read_only=True)
class Meta:
model = Kurs
fields = ["id", "nom", "muallif_ism"]
# → {"id": 1, "nom": "Python", "muallif_ism": "Ali"} source — maydon qiymatini boshqa joydan oladi (muallif.ism — bog'langan model). Bu bog'langan ma'lumotni JSON'ga tekis (flat) chiqaradi (mijoz alohida so'rov qilmasdan). Nuqta bilan chuqur ham (muallif.mamlakat.nom).
2.5. SerializerMethodField
SerializerMethodField — hisoblangan maydon (metod bilan):
class KursSerializer(serializers.ModelSerializer):
chegirmali = serializers.SerializerMethodField()
class Meta:
model = Kurs
fields = ["id", "nom", "narx", "chegirmali"]
def get_chegirmali(self, obj):
return int(obj.narx * 0.9) # 10% chegirma SerializerMethodField — bazada yo'q, hisoblangan maydon (get_<maydon> metodi). Bu qo'shimcha ma'lumot (chegirmali narx, formatlangan sana) JSON'ga qo'shadi. Faqat o'qish uchun (read-only).
2.6. Nested serializer (bog'langan)
Nested serializer — bog'langan ma'lumotni ichkariga joylashtiradi:
class KursSerializer(serializers.ModelSerializer):
class Meta:
model = Kurs
fields = ["id", "nom"]
class MuallifSerializer(serializers.ModelSerializer):
kurslar = KursSerializer(many=True, read_only=True) # nested
class Meta:
model = Muallif
fields = ["id", "ism", "kurslar"]
# → {"id": 1, "ism": "Ali", "kurslar": [{"id": 1, "nom": "Python"}, ...]} Nested serializer — bog'langan obyektlarni (muallif kurslari) JSON'ning ichiga joylashtiradi (bir javobda). many=True — ro'yxat. Bu mijozga bog'langan ma'lumotni bir so'rovda beradi (ko'p so'rov o'rniga).
2.7. read_only / write_only
Maydon yo'nalishini boshqarish:
| Sozlama | Ma'no |
|---|---|
read_only=True |
Faqat o'qish (JSON'da, kirishda yo'q) |
write_only=True |
Faqat yozish (kirishda, JSON'da yo'q) |
id = serializers.IntegerField(read_only=True) # avtomatik
parol = serializers.CharField(write_only=True) # kirish, javobda yo'q read_only — javobda bor, kirishda yo'q (id, hisoblangan); write_only — kirishda bor, javobda yo'q (parol). Bu 20.5 dagi kirish/chiqish modellarini ajratishga o'xshaydi (parol javobda ko'rinmasin).
2.8. Serializer — API shartnomasi
Serializer — API'ning shartnomasi (mijoz nima ko'radi/yuboradi):
| Serializer belgilaydi | Nima |
|---|---|
fields |
Qaysi maydonlar |
validate_* |
Kirish qoidalari |
source/SerializerMethodField |
Maydon manbai |
| Nested | Bog'langan ma'lumot |
read_only/write_only |
Yo'nalish |
Serializer — API'ning aniq shartnomasi: mijoz qaysi maydonni ko'radi (fields), qanday ma'lumot yuboradi (validatsiya), bog'langan ma'lumot qanday (nested). To'g'ri serializer — xavfsiz (kerak maydon), samarali (nested), aniq (shartnoma).
3. Tez ma'lumotnoma
from rest_framework import serializers
class KursSerializer(serializers.ModelSerializer):
muallif_ism = serializers.CharField(source="muallif.ism", read_only=True) # source
chegirmali = serializers.SerializerMethodField() # hisoblangan
parol = serializers.CharField(write_only=True) # faqat kirish
class Meta:
model = Kurs
fields = ["id", "nom", "narx", "muallif_ism", "chegirmali", "parol"]
def get_chegirmali(self, obj): # SerializerMethodField
return int(obj.narx * 0.9)
def validate_narx(self, value): # maydon validatsiyasi
if value < 0:
raise serializers.ValidationError("...")
return value
def validate(self, data): # obyekt validatsiyasi
return dataMaydon sozlamalari
fields — qaysi maydon · source — manba · SerializerMethodField — hisoblangan
validate_<maydon> — maydon · validate — obyekt · read_only/write_only — yo'nalish4. Batafsil misollar
Misollarda DRF serializer bilan sinaladi.
Misol 1 — fields, source va SerializerMethodField
"""fields (qaysi maydon); source (bog'langan manba); SerializerMethodField (hisoblangan maydon)."""
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=["django.contrib.contenttypes", "django.contrib.auth", "rest_framework", "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 rest_framework import serializers
class Muallif(models.Model):
ism = models.CharField(max_length=100)
class Meta:
app_label = "wisar"
class Kurs(models.Model):
nom = models.CharField(max_length=100)
narx = models.IntegerField()
muallif = models.ForeignKey(Muallif, on_delete=models.CASCADE, related_name="kurslar")
class Meta:
app_label = "wisar"
class KursSerializer(serializers.ModelSerializer):
muallif_ism = serializers.CharField(source="muallif.ism", read_only=True)
chegirmali = serializers.SerializerMethodField()
class Meta:
model = Kurs
fields = ["id", "nom", "narx", "muallif_ism", "chegirmali"]
def get_chegirmali(self, obj):
return int(obj.narx * 0.9)
def main() -> None:
for m in (Muallif, Kurs):
with connection.schema_editor() as se:
se.create_model(m)
ali = Muallif.objects.create(ism="Ali")
kurs = Kurs.objects.create(nom="Python", narx=100, muallif=ali)
data = KursSerializer(kurs).data
print("=== 1. fields (tanlangan maydonlar) ===")
print(f" maydonlar: {list(data.keys())}")
print("\n=== 2. source (bog'langan manba) ===")
print(f" muallif_ism (muallif.ism'dan): {data['muallif_ism']}")
print("\n=== 3. SerializerMethodField (hisoblangan) ===")
print(f" narx: {data['narx']}, chegirmali (10%): {data['chegirmali']}")
print("\n=== 4. To'liq JSON ===")
print(f" {dict(data)}")
print(" ⭐ fields — tanlov; source — bog'langan; SerializerMethodField — hisob")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. fields (tanlangan maydonlar) ===
maydonlar: ['id', 'nom', 'narx', 'muallif_ism', 'chegirmali']
=== 2. source (bog'langan manba) ===
muallif_ism (muallif.ism'dan): Ali
=== 3. SerializerMethodField (hisoblangan) ===
narx: 100, chegirmali (10%): 90
=== 4. To'liq JSON ===
{'id': 1, 'nom': 'Python', 'narx': 100, 'muallif_ism': 'Ali', 'chegirmali': 90}
⭐ fields — tanlov; source — bog'langan; SerializerMethodField — hisobNima ko'rsatdi: 2.1, 2.4, 2.5-bo'limlar.
Misol 2 — Validatsiya (validate_<maydon>, validate)
"""maydon validatsiyasi (validate_narx); obyekt validatsiyasi (validate); ValidationError; errors."""
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=["django.contrib.contenttypes", "django.contrib.auth", "rest_framework", "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 rest_framework import serializers
class Kurs(models.Model):
nom = models.CharField(max_length=100)
narx = models.IntegerField()
chegirma = models.IntegerField(default=0)
class Meta:
app_label = "wisar"
class KursSerializer(serializers.ModelSerializer):
class Meta:
model = Kurs
fields = ["nom", "narx", "chegirma"]
def validate_narx(self, value):
if value < 0:
raise serializers.ValidationError("narx manfiy bo'lmasin")
return value
def validate_nom(self, value):
if value.lower() in ("admin", "root"):
raise serializers.ValidationError("bu nom taqiqlangan")
return value.strip()
def validate(self, data):
if data.get("chegirma", 0) > data.get("narx", 0):
raise serializers.ValidationError("chegirma narxdan katta bo'lmasin")
return data
def main() -> None:
with connection.schema_editor() as se:
se.create_model(Kurs)
print("=== 1. To'g'ri ma'lumot ===")
s = KursSerializer(data={"nom": "Python", "narx": 100, "chegirma": 10})
print(f" is_valid: {s.is_valid()}")
print("\n=== 2. ⚠️ Maydon validatsiyasi (manfiy narx) ===")
s = KursSerializer(data={"nom": "Go", "narx": -5})
s.is_valid()
print(f" xato maydon: {list(s.errors.keys())}")
print("\n=== 3. ⚠️ Maydon validatsiyasi (taqiqlangan nom) ===")
s = KursSerializer(data={"nom": "admin", "narx": 100})
s.is_valid()
print(f" xato: {list(s.errors.keys())}")
print("\n=== 4. ⚠️ Obyekt validatsiyasi (chegirma > narx) ===")
s = KursSerializer(data={"nom": "Rust", "narx": 100, "chegirma": 150})
s.is_valid()
print(f" xato: {list(s.errors.keys())}")
print(" ⭐ validate_<maydon> — maydon; validate — obyekt (aloqa)")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. To'g'ri ma'lumot ===
is_valid: True
=== 2. ⚠️ Maydon validatsiyasi (manfiy narx) ===
xato maydon: ['narx']
=== 3. ⚠️ Maydon validatsiyasi (taqiqlangan nom) ===
xato: ['nom']
=== 4. ⚠️ Obyekt validatsiyasi (chegirma > narx) ===
xato: ['non_field_errors']
⭐ validate_<maydon> — maydon; validate — obyekt (aloqa)Nima ko'rsatdi: 2.2, 2.3-bo'limlar.
Misol 3 — Nested serializer va read_only/write_only
"""nested serializer (bog'langan ma'lumot ichkarida); many=True; read_only/write_only; parol yashirish."""
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=["django.contrib.contenttypes", "django.contrib.auth", "rest_framework", "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 rest_framework import serializers
class Muallif(models.Model):
ism = models.CharField(max_length=100)
class Meta:
app_label = "wisar"
class Kurs(models.Model):
nom = models.CharField(max_length=100)
narx = models.IntegerField()
muallif = models.ForeignKey(Muallif, on_delete=models.CASCADE, related_name="kurslar")
class Meta:
app_label = "wisar"
class KursQisqa(serializers.ModelSerializer):
class Meta:
model = Kurs
fields = ["id", "nom", "narx"]
class MuallifSerializer(serializers.ModelSerializer):
kurslar = KursQisqa(many=True, read_only=True) # nested
kurslar_soni = serializers.SerializerMethodField()
class Meta:
model = Muallif
fields = ["id", "ism", "kurslar", "kurslar_soni"]
def get_kurslar_soni(self, obj):
return obj.kurslar.count()
def main() -> None:
for m in (Muallif, Kurs):
with connection.schema_editor() as se:
se.create_model(m)
ali = Muallif.objects.create(ism="Ali")
Kurs.objects.create(nom="Python", narx=100, muallif=ali)
Kurs.objects.create(nom="Go", narx=120, muallif=ali)
data = MuallifSerializer(ali).data
print("=== 1. Nested serializer (kurslar ichkarida) ===")
print(f" muallif: {data['ism']}")
print(f" kurslar (nested): {[k['nom'] for k in data['kurslar']]}")
print("\n=== 2. Bog'langan ma'lumot bir javobda ===")
print(f" birinchi kurs: {dict(data['kurslar'][0])}")
print("\n=== 3. Hisoblangan (kurslar_soni) ===")
print(f" kurslar soni: {data['kurslar_soni']}")
print("\n=== 4. Bir so'rovda to'liq ===")
print(f" maydonlar: {list(data.keys())}")
print(" ⭐ nested — bog'langan ma'lumot ichkarida (bir so'rov)")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Nested serializer (kurslar ichkarida) ===
muallif: Ali
kurslar (nested): ['Python', 'Go']
=== 2. Bog'langan ma'lumot bir javobda ===
birinchi kurs: {'id': 1, 'nom': 'Python', 'narx': 100}
=== 3. Hisoblangan (kurslar_soni) ===
kurslar soni: 2
=== 4. Bir so'rovda to'liq ===
maydonlar: ['id', 'ism', 'kurslar', 'kurslar_soni']
⭐ nested — bog'langan ma'lumot ichkarida (bir so'rov)Nima ko'rsatdi: 2.6, 2.7-bo'limlar.
Misol 4 — Amaliy: to'liq serializer
Barcha serializer imkoniyatlarini birlashtiran to'liq serializer: tanlangan maydonlar, source, hisoblangan maydon, validatsiya, nested va write_only. Bu — real DRF API'ning serializer qatlami.
"""to'liq serializer: fields, source, SerializerMethodField, validate, nested, write_only; API shartnomasi."""
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=["django.contrib.contenttypes", "django.contrib.auth", "rest_framework", "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 rest_framework import serializers
class Muallif(models.Model):
ism = models.CharField(max_length=100)
class Meta:
app_label = "wisar"
class Kurs(models.Model):
nom = models.CharField(max_length=100)
narx = models.IntegerField()
muallif = models.ForeignKey(Muallif, on_delete=models.CASCADE, related_name="kurslar")
class Meta:
app_label = "wisar"
class KursSerializer(serializers.ModelSerializer):
muallif_ism = serializers.CharField(source="muallif.ism", read_only=True)
chegirmali = serializers.SerializerMethodField()
class Meta:
model = Kurs
fields = ["id", "nom", "narx", "muallif", "muallif_ism", "chegirmali"]
extra_kwargs = {"muallif": {"write_only": True}} # kirishda, javobda yo'q
def get_chegirmali(self, obj):
return int(obj.narx * 0.9)
def validate_narx(self, value):
if value < 0:
raise serializers.ValidationError("narx manfiy bo'lmasin")
return value
def main() -> None:
for m in (Muallif, Kurs):
with connection.schema_editor() as se:
se.create_model(m)
ali = Muallif.objects.create(ism="Ali")
kurs = Kurs.objects.create(nom="Python", narx=100, muallif=ali)
print("=== 1. Chiqish (JSON) ===")
data = KursSerializer(kurs).data
print(f" maydonlar: {list(data.keys())}")
print(f" muallif_ism: {data['muallif_ism']}, chegirmali: {data['chegirmali']}")
print("\n=== 2. muallif write_only (javobda yo'q) ===")
print(f" 'muallif' javobda: {'muallif' in data} (write_only)")
print("\n=== 3. Kirish (yaratish) ===")
s = KursSerializer(data={"nom": "Go", "narx": 120, "muallif": ali.id})
print(f" is_valid: {s.is_valid()}")
obj = s.save()
print(f" saqlandi: {obj.nom}, muallif: {obj.muallif.ism}")
print("\n=== 4. Validatsiya (manfiy narx) ===")
s = KursSerializer(data={"nom": "X", "narx": -5, "muallif": ali.id})
s.is_valid()
print(f" xato: {list(s.errors.keys())}")
print(" ⭐ to'liq serializer — fields+source+hisob+validate+write_only")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Chiqish (JSON) ===
maydonlar: ['id', 'nom', 'narx', 'muallif_ism', 'chegirmali']
muallif_ism: Ali, chegirmali: 90
=== 2. muallif write_only (javobda yo'q) ===
'muallif' javobda: False (write_only)
=== 3. Kirish (yaratish) ===
is_valid: True
saqlandi: Go, muallif: Ali
=== 4. Validatsiya (manfiy narx) ===
xato: ['narx']
⭐ to'liq serializer — fields+source+hisob+validate+write_onlyNima ko'rsatdi: 2.1–2.8-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"fields = '__all__' xavfsiz" |
Maxfiy maydon ham (ehtiyot) |
"Validatsiya is_validda yo'q" |
validate_*, validate |
| "Bog'langan — alohida so'rov" | Nested (bir javobda) |
| "Hisoblangan maydon yo'q" | SerializerMethodField |
| "Parol javobda bo'lsin" | write_only |
"source keraksiz" |
Bog'langan/qayta nomlash |
"Nested doim read_only" |
Yozish uchun maxsus mantiq |
| "Serializer = model" | API shartnomasi (moslashuvchan) |
6. Keng tarqalgan xatolar va yechimlari
1. fields = "__all__" (maxfiy maydon)
fields = "__all__" # ⚠️ parol_hash ham
fields = ["id", "nom", "narx"] # ✅ aniq2. Parolni read_onlysiz
parol = serializers.CharField() # ⚠️ javobda ko'rinadi
parol = serializers.CharField(write_only=True) # ✅3. SerializerMethodFieldda get_ unutish
chegirmali = serializers.SerializerMethodField() # get_chegirmali kerak
def get_chegirmali(self, obj): ... # ✅4. validate_<maydon>da return unutish
def validate_narx(self, value):
if value < 0: raise ... # ❌ return yo'q
return value # ✅5. Nested'da many=True unutish
kurslar = KursSerializer(read_only=True) # ❌ ro'yxatda xato
kurslar = KursSerializer(many=True, read_only=True) # ✅6. source bilan bir xil nom
nom = serializers.CharField(source="nom") # ⚠️ keraksiz (xato)
nom = serializers.CharField() # ✅ (source o'zi)7. Obyekt validatsiyasida bir maydon
# bir maydon validate()'da # ⚠️ validate_<maydon> yaxshiroq
def validate(self, data): # ko'p maydon aloqasi # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 21.12-dars (o'tilgan): DRF — serializer asosi
- 21.8-dars (o'tilgan):
ModelForm— taqqoslash - 20.5-dars (o'tilgan): Pydantic — serializer o'xshashi
- 21.10-dars (o'tilgan): bog'lanish — nested serializer
- 21.14-dars: ruxsat — serializer bilan
8. Eng yaxshi amaliyotlar
fieldsni aniq bering ("__all__"ehtiyot).validate_<maydon>/validatebilan validatsiya.write_onlybilan maxfiy maydonni yashiring (parol).sourcebilan bog'langan/qayta nomlash.SerializerMethodFieldbilan hisoblangan maydon.Nested serializer bilan bog'langan ma'lumot (bir so'rov).
Nested'da
many=True(ro'yxatda).Serializer'ni API shartnomasi deb loyihalang.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # fields nima?
2. # "__all__" xavfimi?
3. # validate_<maydon> nima?
4. # validate nima?
5. # source nima?
6. # SerializerMethodField nima?
7. # nested serializer nima?
8. # read_only nima?
9. # write_only nima?
10. # many=True nima?
11. # get_<maydon> nima?
12. # serializer nima (API'da)?Javoblar
- JSON'da qaysi maydonlar
- Ha (maxfiy maydon ham chiqadi)
- Maydon validatsiyasi
- Obyekt validatsiyasi (maydonlar aloqasi)
- Maydon qiymati manbai
- Hisoblangan maydon (metod bilan)
- Bog'langan ma'lumot ichkarida
- Faqat o'qish (javobda, kirishda yo'q)
- Faqat yozish (kirishda, javobda yo'q)
- Ro'yxat serializatsiyasi
SerializerMethodFieldmetodi- API shartnomasi (maydon, validatsiya)
Vazifa 2: Xatolarni tuzating
1. fields = "__all__" # aniq
2. parol = serializers.CharField() # write_only
3. chegirmali = SerializerMethodField() # get_ yo'q
4. def validate_narx(self, v):
if v < 0: raise ... # return
5. kurslar = KursSerializer(read_only=True) # manyJavoblar
1. fields = ["id", "nom", "narx"]
2. parol = serializers.CharField(write_only=True)
3. def get_chegirmali(self, obj): return ...
4. def validate_narx(self, v):
if v < 0: raise ...
return v
5. kurslar = KursSerializer(many=True, read_only=True)Vazifa 3: Serializer maydonlari
To'liq serializer:
fields,source,SerializerMethodFieldread_only/write_only- Har maydon turi
.datatest
Vazifa 4: Validatsiya
Validatsiyali serializer:
validate_<maydon>(bir necha)validate(obyekt)- O'zbekcha xato
- Har holat test
Vazifa 5: Nested serializer
Bog'langan serializer:
- Muallif → kurslar (nested)
- Kurs → muallif (nested)
many=True, hisoblangan- Test
Vazifa 6: Xavfsizlik (write_only)
Parol yashirish:
- Foydalanuvchi serializer
- Parol
write_only - Kirish/chiqish farqi
- Parol javobda yo'qligini test
Vazifa 7: O'ylash
Serializer — API'ning shartnomasi (contract): u mijoz nima ko'radi (fields, nested), qanday ma'lumot yuboradi (validatsiya), qaysi maydon maxfiy (write_only) — hammasini aniq belgilaydi. Bu 20.5 dagi Pydantic, 20.16 dagi OpenAPI kabi "aniq shartnoma" tamoyili. API va uning iste'molchisi (mijoz) o'rtasidagi aniq shartnomaning afzalligi nima, va nima uchun noaniq (hujjatsiz, o'zgaruvchan) shartnoma tizimlarni buzadi?
Javob
Qisqa javob: Serializer API shartnomasini aniq qiladi: mijoz aniq biladi qaysi maydon keladi, qanday format, qanday validatsiya. Aniq shartnoma afzal, chunki mijoz va server mustaqil ishlay oladi (har biri shartnomaga tayanadi). Noaniq shartnoma (hujjatsiz, kutilmagan o'zgaradigan) tizimlarni buzadi: mijoz kutmagan maydon/format kelsa, kod buziladi (masalan, maydon o'chirilsa — mijoz xato). Aniq shartnoma — API va mijoz o'rtasidagi ishonch: har biri ikkinchisining nima qilishini biladi. Bu 20.5 (Pydantic), 20.16 (OpenAPI) kabi.
1. Shartnoma nima
API va mijoz o'rtasidagi kelishuv: qaysi maydon, format, validatsiya. Serializer buni aniq belgilaydi.
2. Aniq shartnoma afzalligi
| Afzallik | Sabab |
|---|---|
| Mustaqillik | Har biri shartnomaga tayanadi |
| Ishonch | Kutilgan format |
| Test | Shartnoma sinaladi |
| Hujjat | Serializer o'zi hujjat |
3. Noaniq shartnoma buzadi
Hujjatsiz/o'zgaruvchan shartnoma:
- Mijoz kutmagan maydon → kod buziladi
- Format o'zgarsa → mijoz xato
- Ishonch yo'q (nima keladi noma'lum)
4. "Aniq shartnoma" boshqa joyda
| Soha | Shartnoma |
|---|---|
| API | Serializer/OpenAPI |
| Funksiya | Tip belgilari |
| Model | Pydantic (20.5) |
| Interfeys | Abstract klass |
5. Muhandislik saboqlari
- API shartnomasini aniq belgila (serializer)
- Aniq shartnoma — mustaqillik, ishonch
- Noaniq shartnoma — buzadi, xato
- Shartnoma — hujjat va test asosi
6. Xulosa
- Serializer — API shartnomasi (aniq)
- Aniq — mijoz mustaqil, ishonchli
- Noaniq — buzadi (kutilmagan)
- Tamoyil keng (Pydantic, OpenAPI, tip)
Nimani mustahkamlaydi: 2.1–2.8-bo'limlar.
Xulosa
Bu darsda DRF serializer'ni chuqurroq o'rgandik.
Eng muhim uch fikr:
Maydonlar va manba.
fields— JSON'ga qaysi maydon kirishini aniq belgilaydi ("__all__"ehtiyot — maxfiy maydon ham).source— maydon qiymatini boshqa joydan oladi (muallif.ism— bog'langan ma'lumotni tekis chiqaradi).SerializerMethodField— bazada yo'q, hisoblangan maydon (get_<maydon>metodi, chegirmali narx).read_only/write_only— maydon yo'nalishini boshqaradi (parol—write_only, javobda ko'rinmasin).Validatsiya va nested.
validate_<maydon>— bir maydon uchun maxsus validatsiya (20.5field_validator, 21.8clean_<maydon>ga o'xshaydi);validate— butun obyekt (maydonlar aloqasi, chegirma < narx). Nested serializer — bog'langan obyektlarni (muallif kurslari) JSON'ning ichiga joylashtiradi (many=True— ro'yxat) — mijozga bog'langan ma'lumotni bir so'rovda beradi (ko'p so'rov o'rniga).Serializer — API shartnomasi. Serializer API'ning aniq shartnomasi: mijoz qaysi maydonni ko'radi (
fields, nested), qanday ma'lumot yuboradi (validatsiya), qaysi maydon maxfiy (write_only). To'g'ri serializer xavfsiz (kerak maydon), samarali (nested — bir so'rov), aniq (shartnoma). Aniq shartnoma API va mijozni mustaqil qiladi — bu 20.5 (Pydantic), 20.16 (OpenAPI) kabi "aniq shartnoma" tamoyili.
Keyingi darsda ruxsat va throttling ni o'rganamiz: DRF'da API'ni himoyalash — permission klasslari, autentifikatsiya va so'rovlar sonini cheklash (rate limiting).
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!