← Назад к вопросам
Чем отличается ModelSerializer от обычного сериалайзера?
2.0 Middle🔥 161 комментариев
#Django#REST API и HTTP
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# ModelSerializer vs Serializer в Django REST Framework
Краткое определение
Serializer — базовый класс для преобразования данных Python в JSON и обратно.
ModelSerializer — специализированный класс, автоматически генерирующий поля на основе Django модели.
# ❌ Ручное определение полей
class UserSerializer(Serializer):
id = IntegerField(read_only=True)
name = CharField(max_length=100)
email = EmailField()
is_active = BooleanField()
created_at = DateTimeField(read_only=True)
# ... ещё 20 полей вручную
# ✅ Автоматическое на основе модели
class UserSerializer(ModelSerializer):
class Meta:
model = User
fields = '__all__' # или ['id', 'name', 'email', ...]
Обычный Serializer
Пример: вручную определяем каждое поле
from rest_framework import serializers
from myapp.models import Article
class ArticleSerializer(serializers.Serializer):
"""Обычный сериалайзер — нужно всё определить вручную"""
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(max_length=200)
content = serializers.CharField()
author = serializers.CharField(max_length=100)
created_at = serializers.DateTimeField(read_only=True)
updated_at = serializers.DateTimeField(read_only=True)
views_count = serializers.IntegerField(default=0)
is_published = serializers.BooleanField(default=False)
def create(self, validated_data):
"""Нужно реализовать создание вручную"""
return Article.objects.create(**validated_data)
def update(self, instance, validated_data):
"""Нужно реализовать обновление вручную"""
instance.title = validated_data.get('title', instance.title)
instance.content = validated_data.get('content', instance.content)
instance.author = validated_data.get('author', instance.author)
instance.is_published = validated_data.get('is_published', instance.is_published)
instance.save()
return instance
Использование:
# Сериализация (объект → JSON)
article = Article.objects.get(id=1)
serializer = ArticleSerializer(article)
print(serializer.data) # {'id': 1, 'title': '...', 'content': '...', ...}
# Десериализация (JSON → объект)
data = {
'title': 'New Article',
'content': 'Content here',
'author': 'John Doe',
'is_published': True
}
serializer = ArticleSerializer(data=data)
if serializer.is_valid():
article = serializer.save() # вызывает create()
else:
print(serializer.errors)
Плюсы Serializer:
- Полный контроль над полями и логикой
- Можно сериализовать что угодно (не только модели)
- Гибкость в кастомизации
Минусы Serializer:
- Много кода
- Легко допустить ошибку
- Дублирование с определением модели
- Нужно вручную реализовать create/update
ModelSerializer
Пример: автоматическое на основе модели
from rest_framework.serializers import ModelSerializer
from myapp.models import Article
class ArticleSerializer(ModelSerializer):
"""ModelSerializer — автоматическое из модели"""
class Meta:
model = Article
fields = ['id', 'title', 'content', 'author', 'created_at', 'is_published']
# или fields = '__all__' # все поля модели
read_only_fields = ['id', 'created_at', 'updated_at']
# Опционально: кастомные валидаторы
def validate_title(self, value):
if len(value) < 3:
raise serializers.ValidationError("Заголовок слишком короткий")
return value
Использование идентично:
# Сериализация
article = Article.objects.get(id=1)
serializer = ArticleSerializer(article)
print(serializer.data)
# Десериализация
data = {'title': '...', 'content': '...', 'author': '...'}
serializer = ArticleSerializer(data=data)
if serializer.is_valid():
article = serializer.save() # create() реализован автоматически
Плюсы ModelSerializer:
- Меньше кода
- Автоматический create/update
- Валидация из модели
- Менее подвержен ошибкам
- DRY (Don't Repeat Yourself)
Сравнение в деталях
1. Определение полей
# Serializer — вручную каждое поле
class ArticleSerializer(Serializer):
id = IntegerField(read_only=True)
title = CharField(max_length=200)
author = CharField(max_length=100)
created_at = DateTimeField(read_only=True)
# Может не совпадать с моделью!
# ModelSerializer — из модели
class ArticleSerializer(ModelSerializer):
class Meta:
model = Article # поля берутся отсюда
fields = '__all__'
2. Create и Update
# Serializer — вручную
class ArticleSerializer(Serializer):
def create(self, validated_data):
return Article.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.title = validated_data.get('title', instance.title)
instance.save()
return instance
# ModelSerializer — автоматически
class ArticleSerializer(ModelSerializer):
class Meta:
model = Article
fields = '__all__'
# create и update уже реализованы!
3. Валидация
# Serializer — вручную
class ArticleSerializer(Serializer):
title = CharField(max_length=200)
def validate_title(self, value):
if Article.objects.filter(title=value).exists():
raise ValidationError("Article with this title exists")
return value
# ModelSerializer — берёт валидацию из модели
class Article(models.Model):
title = models.CharField(
max_length=200,
validators=[UniqueValidator(queryset=Article.objects.all())]
)
class ArticleSerializer(ModelSerializer):
class Meta:
model = Article
fields = ['title']
# Валидация из модели применяется автоматически
4. Связанные объекты (Relationships)
# Модель
class Author(models.Model):
name = models.CharField(max_length=100)
class Article(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
# Serializer — вручную
class ArticleSerializer(Serializer):
id = IntegerField(read_only=True)
title = CharField(max_length=200)
author = IntegerField() # или CharField, или кастомное поле
def create(self, validated_data):
author_id = validated_data.pop('author')
author = Author.objects.get(id=author_id)
return Article.objects.create(author=author, **validated_data)
# ModelSerializer — автоматически
class ArticleSerializer(ModelSerializer):
author = AuthorSerializer(read_only=True) # или PrimaryKeyRelated
class Meta:
model = Article
fields = ['id', 'title', 'author']
Практические примеры
Пример 1: простой CRUD API
from django.db import models
from rest_framework import serializers, viewsets
from rest_framework.routers import DefaultRouter
# Модель
class User(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
age = models.IntegerField()
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
# ModelSerializer
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'name', 'email', 'age', 'is_active']
read_only_fields = ['id']
# ViewSet
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
# Router автоматически создаёт routes
router = DefaultRouter()
router.register(r'users', UserViewSet)
# GET /api/users/ → список
# POST /api/users/ → создание
# GET /api/users/{id}/ → детали
# PUT /api/users/{id}/ → обновление
# DELETE /api/users/{id}/ → удаление
Пример 2: кастомизация ModelSerializer
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.CharField(max_length=50)
views_count = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
class ArticleSerializer(serializers.ModelSerializer):
# Переопределяем поле связи
author = UserSerializer(read_only=True)
author_id = serializers.IntegerField(write_only=True)
# Добавляем кастомное поле
is_popular = serializers.SerializerMethodField()
class Meta:
model = Article
fields = ['id', 'title', 'content', 'author', 'author_id',
'category', 'views_count', 'is_popular', 'created_at']
read_only_fields = ['id', 'views_count', 'created_at']
def get_is_popular(self, obj):
return obj.views_count > 1000
def validate_title(self, value):
if len(value) < 5:
raise serializers.ValidationError("Заголовок слишком короткий")
return value
Пример 3: когда нужен обычный Serializer
# Нужно сериализовать не модель
class CoordinatesSerializer(serializers.Serializer):
latitude = serializers.FloatField(min_value=-90, max_value=90)
longitude = serializers.FloatField(min_value=-180, max_value=180)
altitude = serializers.FloatField()
# Использование
data = {'latitude': 55.75, 'longitude': 37.62, 'altitude': 100}
serializer = CoordinatesSerializer(data=data)
if serializer.is_valid():
print(serializer.validated_data)
# Нужны нестандартные методы create/update
class SpecialSerializer(serializers.Serializer):
value = serializers.IntegerField()
def create(self, validated_data):
# Специальная логика: не просто создать в БД
return do_something_special(validated_data)
Когда использовать что?
# ✅ ModelSerializer, когда:
# - Сериализуешь Django модель
# - Нужны стандартные CRUD операции
# - Валидация из модели
class ArticleSerializer(ModelSerializer):
class Meta:
model = Article
fields = '__all__'
# ✅ Serializer, когда:
# - Сериализуешь не-модель объект
# - Нужна специальная логика create/update
# - Нужна максимальная гибкость
class LocationSerializer(Serializer):
lat = FloatField()
lon = FloatField()
Антипаттерны
# ❌ Переопределять create/update без причины
class ArticleSerializer(ModelSerializer):
class Meta:
model = Article
fields = '__all__'
def create(self, validated_data):
# Без причины переделываем то, что уже есть
return Article.objects.create(**validated_data)
# ✅ Используй стандартную реализацию
class ArticleSerializer(ModelSerializer):
class Meta:
model = Article
fields = '__all__'
# create реализован автоматически
# ❌ Забыть определить поля в Serializer
class UserSerializer(Serializer):
def create(self, validated_data):
return User.objects.create(**validated_data)
# ✅ Определять поля явно или использовать ModelSerializer
class UserSerializer(ModelSerializer):
class Meta:
model = User
fields = '__all__'
Итоги
| Аспект | Serializer | ModelSerializer |
|---|---|---|
| Поля | Вручную | Из модели |
| Create/Update | Вручную | Автоматически |
| Валидация | Вручную | Из модели |
| Код | Больше | Меньше |
| Гибкость | Полная | Ограниченная |
| Используй для | Non-model объекты | Django модели |
| DRY | Нарушает | Соблюдает |
Практическое правило:
- Начни с ModelSerializer — 80% времени её достаточно
- Используй Serializer когда ModelSerializer не подходит
- Помни: ModelSerializer наследуется от Serializer, просто добавляет автоматизацию