← Назад к вопросам
Как с помощью метода serializer создать модель?
1.6 Junior🔥 181 комментариев
#Django#REST API и HTTP
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как с помощью метода serializer создать модель в Django REST Framework
Сериализаторы в Django REST Framework (DRF) — это мощный инструмент для преобразования данных между Python объектами и JSON. Они также позволяют создавать новые модели через валидацию и сохранение данных.
Базовая структура сериализатора
Создание простого сериализатора:
from rest_framework import serializers
from django.contrib.auth.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'email', 'first_name', 'last_name']
read_only_fields = ['id']
# Использование для создания
serializer = UserSerializer(data={
'username': 'john_doe',
'email': 'john@example.com',
'first_name': 'John',
'last_name': 'Doe'
})
if serializer.is_valid():
user = serializer.save() # Создаёт User в БД
print(f"User created: {user.id}")
else:
print(f"Errors: {serializer.errors}")
Валидация перед сохранением
Добавление custom валидации:
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ['id', 'name', 'price', 'stock', 'category']
read_only_fields = ['id']
# 1. Field-level валидация
def validate_price(self, value):
if value <= 0:
raise serializers.ValidationError("Price must be greater than 0")
if value > 1000000:
raise serializers.ValidationError("Price seems too high")
return value
def validate_stock(self, value):
if value < 0:
raise serializers.ValidationError("Stock cannot be negative")
return value
# 2. Object-level валидация
def validate(self, data):
if data['stock'] == 0 and data['price'] > 1000:
raise serializers.ValidationError(
"Cannot have zero stock for expensive products"
)
return data
# Использование
serializer = ProductSerializer(data={
'name': 'Laptop',
'price': 1500,
'stock': 10,
'category': 1
})
if serializer.is_valid():
product = serializer.save()
print(f"Product created: {product.name}")
else:
print(f"Validation errors: {serializer.errors}")
Создание модели с вложенными данными
Работа с ForeignKey:
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
isbn = models.CharField(max_length=13)
pages = models.IntegerField()
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = ['id', 'name', 'email']
class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer()
class Meta:
model = Book
fields = ['id', 'title', 'author', 'isbn', 'pages']
def create(self, validated_data):
author_data = validated_data.pop('author')
author, created = Author.objects.get_or_create(**author_data)
book = Book.objects.create(author=author, **validated_data)
return book
# Использование
data = {
'title': 'Python Advanced',
'isbn': '9781234567890',
'pages': 450,
'author': {
'name': 'Guido van Rossum',
'email': 'guido@python.org'
}
}
serializer = BookSerializer(data=data)
if serializer.is_valid():
book = serializer.save()
print(f"Book created: {book.title} by {book.author.name}")
Создание моделей с ManyToMany отношениями
Работа с множественными связями:
class Course(models.Model):
title = models.CharField(max_length=100)
class Student(models.Model):
name = models.CharField(max_length=100)
courses = models.ManyToManyField(Course)
class StudentSerializer(serializers.ModelSerializer):
courses = serializers.PrimaryKeyRelatedField(
queryset=Course.objects.all(),
many=True
)
class Meta:
model = Student
fields = ['id', 'name', 'courses']
def create(self, validated_data):
courses = validated_data.pop('courses')
student = Student.objects.create(**validated_data)
student.courses.set(courses)
return student
def update(self, instance, validated_data):
courses = validated_data.pop('courses', None)
for attr, value in validated_data.items():
setattr(instance, attr, value)
instance.save()
if courses is not None:
instance.courses.set(courses)
return instance
# Использование
data = {
'name': 'Alice',
'courses': [1, 2, 3]
}
serializer = StudentSerializer(data=data)
if serializer.is_valid():
student = serializer.save()
print(f"Student {student.name} enrolled in {student.courses.count()} courses")
Использование SerializerMethodField
Добавление вычисляемых полей:
class OrderSerializer(serializers.ModelSerializer):
total_price = serializers.SerializerMethodField()
customer_name = serializers.CharField(source='customer.name', read_only=True)
item_count = serializers.SerializerMethodField()
class Meta:
model = Order
fields = ['id', 'customer_name', 'total_price', 'item_count', 'status']
def get_total_price(self, obj):
return obj.items.aggregate(total=models.Sum('price'))['total'] or 0
def get_item_count(self, obj):
return obj.items.count()
Использование в Views
Создание моделей через APIView:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class CreateUserView(APIView):
def post(self, request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
return Response(
UserSerializer(user).data,
status=status.HTTP_201_CREATED
)
return Response(
serializer.errors,
status=status.HTTP_400_BAD_REQUEST
)
Использование в ViewSet
Более элегантный подход:
from rest_framework import viewsets
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
def perform_create(self, serializer):
user = serializer.save()
logger.info(f"User created: {user.id}")
# URL конфиг
from django.urls import path, include
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'users', UserViewSet)
urlpatterns = [
path('api/', include(router.urls)),
]
# Доступные endpoints:
# POST /api/users/ - создание
# GET /api/users/ - список
# PATCH /api/users/<id>/ - частичное обновление
# DELETE /api/users/<id>/ - удаление
Partial updates (частичное обновление)
Обновление только некоторых полей:
class PartialUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['username', 'email', 'first_name']
def update(self, instance, validated_data):
instance.username = validated_data.get('username', instance.username)
instance.email = validated_data.get('email', instance.email)
instance.first_name = validated_data.get('first_name', instance.first_name)
instance.save()
return instance
# Использование
user = User.objects.first()
data = {'email': 'newemail@example.com'}
serializer = PartialUserSerializer(user, data=data, partial=True)
if serializer.is_valid():
serializer.save()
print(f"User updated: {serializer.data}")
Лучшие практики
- Используй ModelSerializer для моделей
- Раздели сериализаторы — read-only и write-only для разных операций
- Валидируй на уровне сериализатора — безопаснее
- SerializerMethodField для вычисляемых полей
- Custom create/update когда нужна сложная логика
- Документируй что какой сериализатор делает
Сериализаторы — это мост между API и БД, правильное их использование обеспечивает надёжное создание и обновление моделей.