Bu darsda ModelSerializer ning barcha imkoniyatlari bilan ishlashni o'rganasiz. Kutubxona Boshqaruv Tizimi (Library Management System) loyihasini yaratish orqali nested serializers, custom fields, validation va boshqa ilg'or texnikalarni amaliyotda ko'rasiz.
Dars oxirida siz:
- β ModelSerializer ning barcha xususiyatlarini bilasiz
- β Nested Serializers (bog'langan modellar) yaratishni o'rganasiz
- β Custom Fields va SerializerMethodField ishlatishni bilasiz
- β Field-level va Object-level validation qilishni o'rganasiz
- β read_only, write_only fieldlar bilan ishlashni bilasiz
- β extra_kwargs orqali konfiguratsiya qilishni o'rganasiz
Kutubxona tizimi - ModelSerializer uchun eng yaxshi misol:
- π 2 ta bog'langan model: Author va Book
- π Nested relationships ko'rsatish oson
- β Validation qoidalari aniq
- π Real-world application
# Yangi papka
mkdir library_api
cd library_api
# Virtual environment
python -m venv env
env\Scripts\activate # Windows
# O'rnatish
pip install django djangorestframework
# Loyiha yaratish
django-admin startproject library_project .
# Ilova yaratish
python manage.py startapp bookslibrary_project/settings.py:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Third-party
'rest_framework',
# Local apps
'books',
]books/models.py:
from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator
class Author(models.Model):
"""
Muallif (Yozuvchi) modeli
Har bir muallif bir nechta kitob yozishi mumkin
"""
# Muallif ismi (majburiy)
# CharField - qisqa matn (maksimal uzunlik bilan)
first_name = models.CharField(
max_length=100,
verbose_name="Ism",
help_text="Muallifning ismi"
)
# Muallif familiyasi (majburiy)
last_name = models.CharField(
max_length=100,
verbose_name="Familiya"
)
# Tug'ilgan yil (ixtiyoriy)
# IntegerField - butun son
# validators - qo'shimcha tekshiruvlar
birth_year = models.IntegerField(
blank=True,
null=True,
verbose_name="Tug'ilgan yil",
validators=[
MinValueValidator(1800), # Minimal 1800-yil
MaxValueValidator(2024) # Maksimal 2024-yil
]
)
# Biografiya (ixtiyoriy)
# TextField - uzun matn (uzunlik chegarasiz)
biography = models.TextField(
blank=True,
null=True,
verbose_name="Biografiya",
help_text="Muallif haqida qisqacha ma'lumot"
)
# Mamlakat (ixtiyoriy)
country = models.CharField(
max_length=100,
blank=True,
null=True,
verbose_name="Mamlakat"
)
# Avtomatik vaqt maydonlari
created_at = models.DateTimeField(
auto_now_add=True,
verbose_name="Qo'shilgan vaqt"
)
class Meta:
verbose_name = "Muallif"
verbose_name_plural = "Mualliflar"
# Familiya, keyin ism bo'yicha tartiblash
ordering = ['last_name', 'first_name']
def __str__(self):
"""
Admin panelda va API da ko'rinish
Return: "Alisher Navoiy"
"""
return f"{self.first_name} {self.last_name}"
def get_full_name(self):
"""
To'liq ismni olish uchun custom metod
"""
return f"{self.first_name} {self.last_name}"
def get_age(self):
"""
Yoshi (agar tug'ilgan yil berilgan bo'lsa)
"""
if self.birth_year:
from datetime import datetime
current_year = datetime.now().year
return current_year - self.birth_year
return None
class Book(models.Model):
"""
Kitob modeli
Har bir kitob bitta muallifga tegishli
"""
# Kitob sarlavhasi (majburiy)
title = models.CharField(
max_length=300,
verbose_name="Sarlavha",
help_text="Kitob nomi"
)
# Muallif (Foreign Key - bog'lanish)
# ForeignKey - boshqa modelga bog'lanish
# on_delete=models.CASCADE - muallif o'chirilsa, uning kitoblari ham o'chiriladi
# related_name='books' - Author obyektidan kitoblarni olish: author.books.all()
author = models.ForeignKey(
Author,
on_delete=models.CASCADE,
related_name='books',
verbose_name="Muallif",
help_text="Kitob muallifi"
)
# ISBN (International Standard Book Number) - unikal kitob kodi
# unique=True - bir xil ISBN 2 marta bo'lmasligi kerak
isbn = models.CharField(
max_length=13,
unique=True,
verbose_name="ISBN",
help_text="13 raqamli ISBN kod"
)
# Chop etilgan yil (majburiy)
published_year = models.IntegerField(
verbose_name="Chop etilgan yil",
validators=[
MinValueValidator(1000),
MaxValueValidator(2024)
]
)
# Sahifalar soni (ixtiyoriy)
pages = models.IntegerField(
blank=True,
null=True,
verbose_name="Sahifalar soni",
validators=[MinValueValidator(1)]
)
# Janr/Tur (tanlov)
# choices - faqat ro'yxatdagi qiymatlardan birini tanlash
GENRE_CHOICES = [
('fiction', 'Badiiy adabiyot'),
('non_fiction', 'Ilmiy adabiyot'),
('poetry', 'She\'riyat'),
('drama', 'Drama'),
('science', 'Fan'),
('history', 'Tarix'),
('biography', 'Biografiya'),
('other', 'Boshqa'),
]
genre = models.CharField(
max_length=20,
choices=GENRE_CHOICES,
default='fiction',
verbose_name="Janr"
)
# Tavsif (ixtiyoriy)
description = models.TextField(
blank=True,
null=True,
verbose_name="Tavsif",
help_text="Kitob haqida qisqacha"
)
# Nusxalar soni kutubxonada (kutubxonada nechta kitob bor)
copies_available = models.IntegerField(
default=1,
verbose_name="Mavjud nusxalar",
validators=[MinValueValidator(0)]
)
# Ijara berilganmi? (boolean)
is_available = models.BooleanField(
default=True,
verbose_name="Mavjud",
help_text="Kutubxonada bormi?"
)
# Avtomatik vaqt maydonlari
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = "Kitob"
verbose_name_plural = "Kitoblar"
# Muallif, keyin sarlavha bo'yicha
ordering = ['author', 'title']
# Database indeksi - qidirishni tezlashtirish
indexes = [
models.Index(fields=['isbn']),
models.Index(fields=['author']),
]
def __str__(self):
"""
Return: "Xamsa - Alisher Navoiy"
"""
return f"{self.title} - {self.author}"
def get_availability_status(self):
"""
Mavjudlik holati
"""
if self.copies_available > 0:
return f"Mavjud ({self.copies_available} nusxa)"
return "Mavjud emas"python manage.py makemigrations
python manage.py migratebooks/serializers.py:
from rest_framework import serializers
from .models import Author, Book
class AuthorSerializer(serializers.ModelSerializer):
"""
Author modelini JSON ga aylantirish
"""
# Custom read-only field - faqat response da ko'rinadi
# SerializerMethodField - custom metod orqali qiymat olish
full_name = serializers.SerializerMethodField()
age = serializers.SerializerMethodField()
books_count = serializers.SerializerMethodField()
class Meta:
model = Author
# Qaysi fieldlar JSON da ko'rinadi
fields = [
'id',
'first_name',
'last_name',
'full_name', # Custom field
'birth_year',
'age', # Custom field
'biography',
'country',
'books_count', # Custom field
'created_at',
]
# Faqat o'qish uchun (create/update da ishlatilmaydi)
read_only_fields = ['id', 'created_at']
# Qo'shimcha sozlamalar (extra_kwargs)
# Bu yerda har bir fieldga maxsus sozlamalar beriladi
extra_kwargs = {
'first_name': {
'required': True, # Majburiy
'error_messages': {
'required': 'Ism kiritilishi shart!',
'blank': 'Ism bo\'sh bo\'lmasligi kerak!'
}
},
'last_name': {
'required': True,
'error_messages': {
'required': 'Familiya kiritilishi shart!',
}
},
'biography': {
'required': False, # Ixtiyoriy
'allow_blank': True, # Bo'sh bo'lishi mumkin
}
}
# Custom field metodlari
# Bu metodlar SerializerMethodField uchun ishlatiladi
# Nomi: get_<field_name>
def get_full_name(self, obj):
"""
To'liq ismni qaytarish
obj - Author obyekti
"""
return obj.get_full_name()
def get_age(self, obj):
"""
Yoshni qaytarish
"""
return obj.get_age()
def get_books_count(self, obj):
"""
Muallif yozgan kitoblar soni
obj.books - related_name orqali barcha kitoblar
"""
return obj.books.count()
# VALIDATION metodlari
def validate_first_name(self, value):
"""
Ismni tekshirish
value - foydalanuvchi kiritgan ism
"""
# Bo'sh joylarni olib tashlash
value = value.strip()
# Kamida 2 ta belgi
if len(value) < 2:
raise serializers.ValidationError(
"Ism kamida 2 ta belgidan iborat bo'lishi kerak!"
)
# Faqat harflar va bo'sh joy
if not all(char.isalpha() or char.isspace() for char in value):
raise serializers.ValidationError(
"Ismda faqat harflar bo'lishi mumkin!"
)
# Birinchi harfni katta qilish
value = value.title()
return value
def validate_last_name(self, value):
"""
Familiyani tekshirish
"""
value = value.strip()
if len(value) < 2:
raise serializers.ValidationError(
"Familiya kamida 2 ta belgidan iborat bo'lishi kerak!"
)
value = value.title()
return value
def validate_birth_year(self, value):
"""
Tug'ilgan yilni tekshirish
"""
if value: # Agar berilgan bo'lsa (ixtiyoriy field)
from datetime import datetime
current_year = datetime.now().year
# Kelajakda bo'lmasligi kerak
if value > current_year:
raise serializers.ValidationError(
"Tug'ilgan yil kelajakda bo'lishi mumkin emas!"
)
# Juda eski bo'lmasligi kerak
if value < 1800:
raise serializers.ValidationError(
"Tug'ilgan yil 1800 dan kichik bo'lmasligi kerak!"
)
return value
def validate(self, data):
"""
Umum validation - barcha fieldlar birgalikda tekshiriladi
data - dict ko'rinishida barcha ma'lumotlar
"""
# Ism va familiya bir xil bo'lmasligi kerak
if 'first_name' in data and 'last_name' in data:
if data['first_name'].lower() == data['last_name'].lower():
raise serializers.ValidationError({
'last_name': "Ism va familiya bir xil bo'lishi mumkin emas!"
})
return dataclass BookSerializer(serializers.ModelSerializer):
"""
Book modelini JSON ga aylantirish
"""
# Nested serializer - Author ma'lumotlarini ham ko'rsatish
# read_only=True - faqat GET da ko'rinadi, POST/PUT da yo'q
author_detail = AuthorSerializer(source='author', read_only=True)
# write_only field - faqat POST/PUT da ishlatiladi, response da ko'rinmaydi
# author_id ni yuborish orqali muallif tanlanadi
author_id = serializers.IntegerField(write_only=True)
# Custom fields
availability_status = serializers.SerializerMethodField()
genre_display = serializers.CharField(source='get_genre_display', read_only=True)
class Meta:
model = Book
fields = [
'id',
'title',
'author_id', # write_only - faqat POST/PUT da
'author_detail', # read_only - faqat GET da
'isbn',
'published_year',
'pages',
'genre',
'genre_display', # Janr nomi (Badiiy adabiyot)
'description',
'copies_available',
'is_available',
'availability_status', # Custom field
'created_at',
'updated_at',
]
read_only_fields = ['id', 'created_at', 'updated_at']
extra_kwargs = {
'title': {
'required': True,
'error_messages': {
'required': 'Kitob sarlavhasi kiritilishi shart!',
'blank': 'Sarlavha bo\'sh bo\'lmasligi kerak!'
}
},
'isbn': {
'required': True,
'error_messages': {
'unique': 'Bu ISBN kod allaqachon mavjud!',
}
},
'published_year': {
'required': True,
}
}
def get_availability_status(self, obj):
"""
Mavjudlik holati
"""
return obj.get_availability_status()
# VALIDATION
def validate_title(self, value):
"""
Sarlavhani tekshirish
"""
value = value.strip()
if len(value) < 3:
raise serializers.ValidationError(
"Kitob sarlavhasi kamida 3 ta belgidan iborat bo'lishi kerak!"
)
# Birinchi harfni katta qilish
value = value.title()
return value
def validate_isbn(self, value):
"""
ISBN ni tekshirish
ISBN - 10 yoki 13 raqamli bo'lishi kerak
"""
# Bo'sh joylar va chiziqlarni olib tashlash
value = value.replace('-', '').replace(' ', '').strip()
# Faqat raqamlardan iborat bo'lishi kerak
if not value.isdigit():
raise serializers.ValidationError(
"ISBN faqat raqamlardan iborat bo'lishi kerak!"
)
# Uzunligi 10 yoki 13 bo'lishi kerak
if len(value) not in [10, 13]:
raise serializers.ValidationError(
"ISBN 10 yoki 13 raqamli bo'lishi kerak!"
)
return value
def validate_published_year(self, value):
"""
Chop etilgan yilni tekshirish
"""
from datetime import datetime
current_year = datetime.now().year
if value > current_year:
raise serializers.ValidationError(
"Chop etilgan yil kelajakda bo'lishi mumkin emas!"
)
if value < 1000:
raise serializers.ValidationError(
"Chop etilgan yil 1000 dan kichik bo'lmasligi kerak!"
)
return value
def validate_pages(self, value):
"""
Sahifalar sonini tekshirish
"""
if value and value < 1:
raise serializers.ValidationError(
"Sahifalar soni 1 dan kam bo'lmasligi kerak!"
)
return value
def validate_copies_available(self, value):
"""
Nusxalar sonini tekshirish
"""
if value < 0:
raise serializers.ValidationError(
"Nusxalar soni manfiy bo'lishi mumkin emas!"
)
return value
def validate_author_id(self, value):
"""
Muallif ID sini tekshirish
"""
# Author database da borligini tekshirish
try:
Author.objects.get(id=value)
except Author.DoesNotExist:
raise serializers.ValidationError(
f"ID={value} muallif topilmadi!"
)
return value
def validate(self, data):
"""
Umum validation
"""
# Agar nusxalar soni 0 bo'lsa, is_available False bo'lishi kerak
if 'copies_available' in data:
if data['copies_available'] == 0:
data['is_available'] = False
else:
data['is_available'] = True
# Kitob chop etilgan yil muallifning tug'ilgan yilidan keyin bo'lishi kerak
if 'author_id' in data and 'published_year' in data:
author = Author.objects.get(id=data['author_id'])
if author.birth_year and data['published_year'] < author.birth_year:
raise serializers.ValidationError({
'published_year': "Kitob muallif tug'ilganidan oldin chop etilgan bo'lishi mumkin emas!"
})
return data
def create(self, validated_data):
"""
Yangi kitob yaratish
validated_data - tekshirilgan ma'lumotlar
"""
# author_id ni author obyektga aylantirish
author_id = validated_data.pop('author_id')
author = Author.objects.get(id=author_id)
# Kitob yaratish
book = Book.objects.create(author=author, **validated_data)
return book
def update(self, instance, validated_data):
"""
Kitobni yangilash
instance - yangilanayotgan kitob
validated_data - yangi ma'lumotlar
"""
# Agar author_id berilgan bo'lsa
if 'author_id' in validated_data:
author_id = validated_data.pop('author_id')
instance.author = Author.objects.get(id=author_id)
# Boshqa fieldlarni yangilash
for attr, value in validated_data.items():
setattr(instance, attr, value)
instance.save()
return instanceclass AuthorListSerializer(serializers.ModelSerializer):
"""
Ro'yxat uchun qisqa serializer - faqat asosiy ma'lumotlar
"""
full_name = serializers.SerializerMethodField()
books_count = serializers.SerializerMethodField()
class Meta:
model = Author
fields = ['id', 'full_name', 'country', 'books_count']
def get_full_name(self, obj):
return obj.get_full_name()
def get_books_count(self, obj):
return obj.books.count()
class BookListSerializer(serializers.ModelSerializer):
"""
Kitoblar ro'yxati uchun qisqa serializer
"""
author_name = serializers.CharField(source='author.get_full_name', read_only=True)
genre_display = serializers.CharField(source='get_genre_display', read_only=True)
class Meta:
model = Book
fields = [
'id',
'title',
'author_name',
'genre_display',
'published_year',
'is_available',
]books/views.py:
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from .models import Author, Book
from .serializers import (
AuthorSerializer,
AuthorListSerializer,
BookSerializer,
BookListSerializer
)
# ============ AUTHOR VIEWS ============
@api_view(['GET', 'POST'])
def author_list(request):
"""
GET: Barcha mualliflar
POST: Yangi muallif yaratish
"""
if request.method == 'GET':
authors = Author.objects.all()
# List uchun qisqa serializer
serializer = AuthorListSerializer(authors, many=True)
return Response(serializer.data)
elif request.method == 'POST':
# Create uchun to'liq serializer
serializer = AuthorSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'PUT', 'PATCH', 'DELETE'])
def author_detail(request, pk):
"""
GET: Bitta muallifni ko'rish
PUT/PATCH: Yangilash
DELETE: O'chirish
"""
try:
author = Author.objects.get(pk=pk)
except Author.DoesNotExist:
return Response(
{'error': f'ID={pk} muallif topilmadi!'},
status=status.HTTP_404_NOT_FOUND
)
if request.method == 'GET':
serializer = AuthorSerializer(author)
return Response(serializer.data)
elif request.method in ['PUT', 'PATCH']:
partial = request.method == 'PATCH'
serializer = AuthorSerializer(author, data=request.data, partial=partial)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
author.delete()
return Response(
{'message': 'Muallif o\'chirildi!'},
status=status.HTTP_204_NO_CONTENT
)
# ============ BOOK VIEWS ============
@api_view(['GET', 'POST'])
def book_list(request):
"""
GET: Barcha kitoblar
POST: Yangi kitob yaratish
"""
if request.method == 'GET':
books = Book.objects.all()
serializer = BookListSerializer(books, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = BookSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'PUT', 'PATCH', 'DELETE'])
def book_detail(request, pk):
"""
GET: Bitta kitobni ko'rish
PUT/PATCH: Yangilash
DELETE: O'chirish
"""
try:
book = Book.objects.get(pk=pk)
except Book.DoesNotExist:
return Response(
{'error': f'ID={pk} kitob topilmadi!'},
status=status.HTTP_404_NOT_FOUND
)
if request.method == 'GET':
serializer = BookSerializer(book)
return Response(serializer.data)
elif request.method in ['PUT', 'PATCH']:
partial = request.method == 'PATCH'
serializer = BookSerializer(book, data=request.data, partial=partial)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
book.delete()
return Response(
{'message': 'Kitob o\'chirildi!'},
status=status.HTTP_204_NO_CONTENT
)
# ============ CUSTOM ENDPOINTS ============
@api_view(['GET'])
def author_books(request, pk):
"""
Muallif yozgan barcha kitoblar
URL: /api/authors/<id>/books/
"""
try:
author = Author.objects.get(pk=pk)
except Author.DoesNotExist:
return Response(
{'error': 'Muallif topilmadi!'},
status=status.HTTP_404_NOT_FOUND
)
# related_name orqali barcha kitoblar
books = author.books.all()
serializer = BookListSerializer(books, many=True)
return Response({
'author': author.get_full_name(),
'books_count': books.count(),
'books': serializer.data
})
@api_view(['GET'])
def available_books(request):
"""
Faqat mavjud kitoblar
URL: /api/books/available/
"""
books = Book.objects.filter(is_available=True, copies_available__gt=0)
serializer = BookListSerializer(books, many=True)
return Response({
'count': books.count(),
'books': serializer.data
})books/urls.py:
from django.urls import path
from . import views
app_name = 'books'
urlpatterns = [
# Authors
path('authors/', views.author_list, name='author-list'),
path('authors/<int:pk>/', views.author_detail, name='author-detail'),
path('authors/<int:pk>/books/', views.author_books, name='author-books'),
# Books
path('books/', views.book_list, name='book-list'),
path('books/<int:pk>/', views.book_detail, name='book-detail'),
path('books/available/', views.available_books, name='available-books'),
]library_project/urls.py:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('books.urls')),
]books/admin.py:
from django.contrib import admin
from .models import Author, Book
@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
list_display = ['id', 'first_name', 'last_name', 'country', 'birth_year']
list_filter = ['country', 'birth_year']
search_fields = ['first_name', 'last_name']
readonly_fields = ['created_at']
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
list_display = [
'id',
'title',
'author',
'isbn',
'published_year',
'genre',
'is_available',
'copies_available'
]
list_filter = ['genre', 'is_available', 'published_year']
search_fields = ['title', 'isbn', 'author__first_name', 'author__last_name']
list_editable = ['is_available', 'copies_available']
readonly_fields = ['created_at', 'updated_at']
fieldsets = (
('Asosiy Ma\'lumotlar', {
'fields': ('title', 'author', 'isbn')
}),
('Nashr Ma\'lumotlari', {
'fields': ('published_year', 'pages', 'genre', 'description')
}),
('Mavjudlik', {
'fields': ('copies_available', 'is_available')
}),
('Vaqt', {
'fields': ('created_at', 'updated_at'),
'classes': ('collapse',)
}),
)Superuser yaratish:
python manage.py createsuperuserpython manage.py runserverMuallif yaratish:
curl -X POST http://127.0.0.1:8000/api/authors/ \
-H "Content-Type: application/json" \
-d '{
"first_name": "Alisher",
"last_name": "Navoiy",
"birth_year": 1441,
"biography": "O'\''zbek mumtoz adabiyotining buyuk namoyandasi",
"country": "O'\''zbekiston"
}'Kitob yaratish:
curl -X POST http://127.0.0.1:8000/api/books/ \
-H "Content-Type: application/json" \
-d '{
"title": "Xamsa",
"author_id": 1,
"isbn": "9785990001234",
"published_year": 1485,
"pages": 500,
"genre": "poetry",
"description": "Besh dostondan iborat asarlar to'\''plami",
"copies_available": 5
}'Barcha kitoblar:
curl http://127.0.0.1:8000/api/books/Muallif kitoblari:
curl http://127.0.0.1:8000/api/authors/1/books/Maqsad: BookSerializer ga yangi custom field qo'shish
Topshiriq:
years_since_publishedfield qo'shing (nechi yil oldin chop etilgan)is_old_bookfield qo'shing (50 yildan eski kitoblar uchun True)- API testdan o'tkazing
Yechim ko'rsatma:
years_since_published = serializers.SerializerMethodField()
def get_years_since_published(self, obj):
from datetime import datetime
current_year = datetime.now().year
return current_year - obj.published_yearMaqsad: Qo'shimcha validation qoidalari qo'shish
Topshiriq:
- Author uchun: Ism va familiya faqat harflardan iborat bo'lishi
- Book uchun: Agar sahifalar soni berilgan bo'lsa, 10 dan kam bo'lmasligi
- Book uchun: Chop etilgan yil muallif vafot etgan yildan katta bo'lmasligi (optional)
Tekshirish:
- Noto'g'ri ma'lumot yuborib, xato qaytishini ko'ring
- To'g'ri ma'lumot yuborib, muvaffaqiyatli yaratishni tekshiring
Maqsad: Yangi model qo'shib, nested serializer yaratish
Topshiriq:
Publishermodelini yarating (name, country, founded_year)BookmodeligapublisherForeignKey qo'shingPublisherSerializeryaratingBookSerializerda publisher ma'lumotlarini nested ko'rsating- CRUD operatsiyalarini amalga oshiring
Qo'shimcha:
- Publisher yozgan barcha kitoblar endpoint:
/api/publishers/<id>/books/ - Eng ko'p kitob chop etgan nashriyot:
/api/publishers/top/
Maqsad: Qidiruv funksiyasini qo'shish
Topshiriq:
- Kitoblarni sarlavha bo'yicha qidirish:
/api/books/search/?q=xamsa - Kitoblarni janr bo'yicha filtrlash:
/api/books/?genre=poetry - Kitoblarni muallif bo'yicha filtrlash:
/api/books/?author=1 - Bir nechta filtrni birga ishlatish
Maslahat:
@api_view(['GET'])
def search_books(request):
query = request.GET.get('q', '')
books = Book.objects.filter(title__icontains=query)
# ...β Dars 04 tugadi! ModelSerializer ning barcha imkoniyatlarini o'rgandingiz!
Keyingi darsda:
- Generic Views
- Mixins
- ViewSets
| Xususiyat | Vazifasi | Misol |
|---|---|---|
fields |
Qaysi fieldlar JSON da | ['id', 'title'] |
exclude |
Qaysi fieldlar chiqarib tashlanadi | ['password'] |
read_only_fields |
Faqat o'qish | ['id', 'created_at'] |
extra_kwargs |
Field sozlamalari | {'title': {'required': True}} |
SerializerMethodField |
Custom field | get_full_name() |
- Field-level:
validate_<field_name>(self, value) - Object-level:
validate(self, data) - Model-level: Model da
clean()metodi
# Read-only
author_detail = AuthorSerializer(source='author', read_only=True)
# Write-only
author_id = serializers.IntegerField(write_only=True)Β© 2024 Deepcode Academy. Barcha huquqlar himoyalangan.