IlmHamroh
Python kursi/Django13/16-dars16 daqiqa
Mundarija (22)

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:

python
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:

python
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):

python
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:

python
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):

python
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:

python
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)
python
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

python
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 data

Maydon sozlamalari

fields — qaysi maydon · source — manba · SerializerMethodField — hisoblangan
validate_<maydon> — maydon · validate — obyekt · read_only/write_only — yo'nalish

4. Batafsil misollar

Misollarda DRF serializer bilan sinaladi.

Misol 1 — fields, source va SerializerMethodField

python
"""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:

text
=== 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 — hisob

Nima ko'rsatdi: 2.1, 2.4, 2.5-bo'limlar.

Misol 2 — Validatsiya (validate_<maydon>, validate)

python
"""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:

text
=== 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

python
"""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:

text
=== 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.

python
"""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:

text
=== 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_only

Nima 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)

python
fields = "__all__"                           # ⚠️ parol_hash ham
fields = ["id", "nom", "narx"]               # ✅ aniq

2. Parolni read_onlysiz

python
parol = serializers.CharField()              # ⚠️ javobda ko'rinadi
parol = serializers.CharField(write_only=True)   # ✅

3. SerializerMethodFieldda get_ unutish

python
chegirmali = serializers.SerializerMethodField()   # get_chegirmali kerak
def get_chegirmali(self, obj): ...           # ✅

4. validate_<maydon>da return unutish

python
def validate_narx(self, value):
    if value < 0: raise ...                  # ❌ return yo'q
    return value                              # ✅

5. Nested'da many=True unutish

python
kurslar = KursSerializer(read_only=True)     # ❌ ro'yxatda xato
kurslar = KursSerializer(many=True, read_only=True)   # ✅

6. source bilan bir xil nom

python
nom = serializers.CharField(source="nom")    # ⚠️ keraksiz (xato)
nom = serializers.CharField()                # ✅ (source o'zi)

7. Obyekt validatsiyasida bir maydon

python
# 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

  1. fieldsni aniq bering ("__all__" ehtiyot).

  2. validate_<maydon>/validate bilan validatsiya.

  3. write_only bilan maxfiy maydonni yashiring (parol).

  4. source bilan bog'langan/qayta nomlash.

  5. SerializerMethodField bilan hisoblangan maydon.

  6. Nested serializer bilan bog'langan ma'lumot (bir so'rov).

  7. Nested'da many=True (ro'yxatda).

  8. Serializer'ni API shartnomasi deb loyihalang.


9. Amaliy topshiriq

Vazifa 1: Bashorat qiling

python
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
  1. JSON'da qaysi maydonlar
  2. Ha (maxfiy maydon ham chiqadi)
  3. Maydon validatsiyasi
  4. Obyekt validatsiyasi (maydonlar aloqasi)
  5. Maydon qiymati manbai
  6. Hisoblangan maydon (metod bilan)
  7. Bog'langan ma'lumot ichkarida
  8. Faqat o'qish (javobda, kirishda yo'q)
  9. Faqat yozish (kirishda, javobda yo'q)
  10. Ro'yxat serializatsiyasi
  11. SerializerMethodField metodi
  12. API shartnomasi (maydon, validatsiya)

Vazifa 2: Xatolarni tuzating

python
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)   # many
Javoblar
python
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:

  1. fields, source, SerializerMethodField
  2. read_only/write_only
  3. Har maydon turi
  4. .data test

Vazifa 4: Validatsiya

Validatsiyali serializer:

  1. validate_<maydon> (bir necha)
  2. validate (obyekt)
  3. O'zbekcha xato
  4. Har holat test

Vazifa 5: Nested serializer

Bog'langan serializer:

  1. Muallif → kurslar (nested)
  2. Kurs → muallif (nested)
  3. many=True, hisoblangan
  4. Test

Vazifa 6: Xavfsizlik (write_only)

Parol yashirish:

  1. Foydalanuvchi serializer
  2. Parol write_only
  3. Kirish/chiqish farqi
  4. 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

  1. API shartnomasini aniq belgila (serializer)
  2. Aniq shartnoma — mustaqillik, ishonch
  3. Noaniq shartnoma — buzadi, xato
  4. Shartnoma — hujjat va test asosi

6. Xulosa

  1. Serializer — API shartnomasi (aniq)
  2. Aniq — mijoz mustaqil, ishonchli
  3. Noaniq — buzadi (kutilmagan)
  4. 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:

  1. 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).

  2. Validatsiya va nested. validate_<maydon> — bir maydon uchun maxsus validatsiya (20.5 field_validator, 21.8 clean_<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).

  3. 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).

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
21.13-dars: Serializer — IlmHamroh