AXV

Model, View va Serializer. Routerlar

Django REST Framework-ning yuragi: Modellar, Serializerlar, ViewSetlar va marshrutlash

10-sinfAdvanced Python Back-end1-hafta · 3-dars

Dars rejasi

Django ORM & Modellar

TimeStampedModel, Category, Tag, Post va Comment modellarini yaratish.

Serializer & N+1 Yechimi

ModelSerializer, Read va Write serializerlari, select_related va prefetch_related.

ViewSets & Routers

ModelViewSet, DefaultRouter va Browsable API orqali testlash.

01

Django ORM va Modellar

NewsPortal ma'lumotlar bazasi jadvallari

Abstrakt model: TimeStampedModel

Barcha modellar uchun umumiy yaratilgan va yangilangan vaqt tamoyili

# src/apps/common/models.py
from django.db import models

class TimeStampedModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True  # Alohida jadval ochilmaydi
abstract = True kodi Djangoga bu modeldan faqat meros olish uchun foydalanishni buyuradi.

NewsPortal: Post modeli

# src/apps/news/models.py (qisqartirilgan)
class Post(TimeStampedModel):
    title = models.CharField(max_length=220)
    slug = models.SlugField(max_length=240, unique=True)
    body = models.TextField()
    category = models.ForeignKey(
        Category, on_delete=models.PROTECT, related_name="posts"
    )
    tags = models.ManyToManyField(Tag, blank=True, related_name="posts")

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super().save(*args, **kwargs)
02

Serializer qatlami

Python obyektlari va JSON o'rtasidagi ko'prik

Serializer qanday ishlaydi?

Serialization (Chiqarish) va Deserialization (Qabul qilish va tekshirish)

Django Model <Post: Sun'iy intellekt> QuerySet obyektlari Python ichki formati Serializer 1. Serialization (Model → JSON) 2. Deserialization (JSON → Model) is_valid() tekshiruvi Frontend / Client {"title": "AI...", ...} Universal JSON matni Brauzer, Mobil, Bot

Nega ikkita alohida serializer kerak?

PostListSerializer (Read)

O'qish uchun: kategoriya va teglarning to'liq ma'lumotlari (nomi, slug) kerak.

{
  "title": "Yangilik",
  "category": { "id": 1, "name": "IT" }
}
VS

PostWriteSerializer (Write)

Yozish uchun: mijozdan ortiqcha matn emas, faqat kategoriya ID raqami so'raladi.

{
  "title": "Yangi post",
  "category": 1
}
03

N+1 muammosi va yechim

Ma'lumotlar bazasi so'rovlarini optimallashtirish

N+1 muammosi qanday yuz beradi?

1 ta so'rov o'rniga 101 ta so'rov yuborilishi serverni "cho'ktiradi"

Oddiy Post.objects.all() 1. Postlarni oladi: 1 ta so'rov 2. Har post uchun kategoriyani so'raydi 100 ta post = 101 ta SQL so'rov! Juda sekin va samarasiz select_related("category") SQL INNER JOIN ishlatadi Post va kategoriyani birdan oladi 100 ta post = 1 ta SQL so'rov! 10 barobar tezroq ishlash!

Qachon qaysi birini ishlatamiz?

select_related()

One-to-One va One-to-Many (ForeignKey) uchun ishlatiladi.

SQL JOIN orqali bitta so'rovda bog'laydi.

prefetch_related()

Many-to-Many va teskari bog'lanishlar uchun ishlatiladi.

Alohida 1 ta optimallashgan qo'shimcha so'rov yuboradi.

04

ViewSets va Routerlar

To'liq CRUD va avtomatik marshrutlash

src/apps/news/views.py (PostViewSet)

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.select_related("category") \
                           .prefetch_related("tags").all()
    lookup_field = "slug"

    def get_serializer_class(self):
        if self.action in ("create", "update", "partial_update"):
            return PostWriteSerializer
        if self.action == "retrieve":
            return PostDetailSerializer
        return PostListSerializer

DefaultRouter qanday ishlaydi?

1 qator kod 6 ta standart REST API marshrutini shakllantiradi

DefaultRouter router.register( "posts", PostViewSet) GET /api/v1/posts/ → list POST /api/v1/posts/ → create GET /api/v1/posts/{slug}/ → retrieve PUT /api/v1/posts/{slug}/ → update DELETE /api/v1/posts/{slug}/ → destroy

API ni brauzerda tekshirish

http://127.0.0.1:8000/api/v1/posts/

HTTP 200 OK

[
  {
    "id": 1,
    "title": "Sun'iy intellekt kelajagi",
    "slug": "suniy-intellekt-kelajagi",
    "category": { "id": 2, "name": "IT" }
  }
]

Atamalarni eslab qolamiz

Serializer

Bosing va tekshiring

Tarjimon

Django modelini JSON ga va JSON ni modelga o'tkazuvchi qatlam.

select_related

Bosing va tekshiring

SQL JOIN

ForeignKey bog'lanishlarini 1 ta so'rov bilan olib keluvchi optimizator.

Router

Bosing va tekshiring

Marshrutchi

Barcha CRUD endpointlarini avtomatik yaratib beruvchi vosita.

Tezkor bilim tekshiruvi

Nima uchun ManyToMany maydonlar uchun select_related emas, prefetch_related ishlatiladi?

To'g'ri! ManyToMany bog'lanishlarda SQL JOIN ma'lumotlar hajmini keskin oshiradi. Shuning uchun Django prefetch_related orqali alohida qo'shimcha so'rov bilan birlashtiradi.

Dasturchilar ko'p yo'l qo'yadigan xatolar

Xato: Har bir model uchun bitta yagona serializer yozib, unda barcha maydonlarni majburiy qilib qo'yish.
To'g'ri: Read va Write uchun serializerlarni ajrating (PostListSerializer va PostWriteSerializer).

Amaliy topshiriq 20 daqiqa

Oson CategorySerializer va TagSerializer klasslarini yozing.
O'rta PostViewSet ni select_related bilan yozing va get_serializer_class ni ulang.
Qiyin DefaultRouter orqali barcha ViewSetlarni ulab, Browsable API orqali dastlabki maqolani yarating.
AXV

1-haftani muvaffaqiyatli yakunladik!

Keyingi haftada: Foydalanuvchilarni boshqarish, Custom User, JWT va Ruxsatlar (Permissions) bilan ishlaymiz!

Django ORM ModelSerializer select_related ModelViewSet & Router