363 lines
11 KiB
Python
363 lines
11 KiB
Python
"""
|
||
Сериализаторы для интерактивной доски.
|
||
"""
|
||
from rest_framework import serializers
|
||
from .models import Board, BoardElement, BoardSnapshot
|
||
from apps.users.serializers import UserSerializer
|
||
|
||
|
||
class BoardElementSerializer(serializers.ModelSerializer):
|
||
"""Сериализатор элемента доски."""
|
||
|
||
created_by = UserSerializer(read_only=True)
|
||
locked_by = UserSerializer(read_only=True)
|
||
|
||
class Meta:
|
||
model = BoardElement
|
||
fields = [
|
||
'id',
|
||
'board',
|
||
'element_type',
|
||
'x',
|
||
'y',
|
||
'width',
|
||
'height',
|
||
'rotation',
|
||
'z_index',
|
||
'content',
|
||
'font_size',
|
||
'font_family',
|
||
'font_weight',
|
||
'text_align',
|
||
'text_color',
|
||
'shape_type',
|
||
'fill_color',
|
||
'stroke_color',
|
||
'stroke_width',
|
||
'opacity',
|
||
'image_url',
|
||
'drawing_data',
|
||
'arrow_start_element',
|
||
'arrow_end_element',
|
||
'created_by',
|
||
'locked',
|
||
'locked_by',
|
||
'is_deleted',
|
||
'created_at',
|
||
'updated_at'
|
||
]
|
||
read_only_fields = [
|
||
'created_by',
|
||
'locked_by',
|
||
'is_deleted',
|
||
'created_at',
|
||
'updated_at'
|
||
]
|
||
|
||
|
||
class BoardElementCreateSerializer(serializers.ModelSerializer):
|
||
"""Сериализатор создания элемента доски."""
|
||
|
||
board_id = serializers.UUIDField(write_only=True)
|
||
|
||
class Meta:
|
||
model = BoardElement
|
||
fields = [
|
||
'board_id',
|
||
'element_type',
|
||
'x',
|
||
'y',
|
||
'width',
|
||
'height',
|
||
'rotation',
|
||
'z_index',
|
||
'content',
|
||
'font_size',
|
||
'font_family',
|
||
'font_weight',
|
||
'text_align',
|
||
'text_color',
|
||
'shape_type',
|
||
'fill_color',
|
||
'stroke_color',
|
||
'stroke_width',
|
||
'opacity',
|
||
'image_url',
|
||
'drawing_data',
|
||
]
|
||
|
||
def validate_board_id(self, value):
|
||
"""Проверка доски."""
|
||
try:
|
||
board = Board.objects.get(board_id=value)
|
||
except Board.DoesNotExist:
|
||
raise serializers.ValidationError('Доска не найдена')
|
||
|
||
# Проверяем доступ
|
||
user = self.context['request'].user
|
||
if not board.has_access(user):
|
||
raise serializers.ValidationError('У вас нет доступа к этой доске')
|
||
|
||
return value
|
||
|
||
def create(self, validated_data):
|
||
"""Создание элемента."""
|
||
board_id = validated_data.pop('board_id')
|
||
board = Board.objects.get(board_id=board_id)
|
||
user = self.context['request'].user
|
||
|
||
element = BoardElement.objects.create(
|
||
board=board,
|
||
created_by=user,
|
||
**validated_data
|
||
)
|
||
|
||
# Обновляем счетчик элементов
|
||
board.update_elements_count()
|
||
|
||
# Отмечаем редактирование
|
||
board.mark_edited(user)
|
||
|
||
return element
|
||
|
||
|
||
class BoardSerializer(serializers.ModelSerializer):
|
||
"""Сериализатор доски."""
|
||
|
||
owner = UserSerializer(read_only=True)
|
||
mentor = UserSerializer(read_only=True)
|
||
student = UserSerializer(read_only=True)
|
||
participants = UserSerializer(many=True, read_only=True)
|
||
last_edited_by = UserSerializer(read_only=True)
|
||
elements = BoardElementSerializer(many=True, read_only=True)
|
||
files_count = serializers.SerializerMethodField()
|
||
snapshot_elements_count = serializers.SerializerMethodField()
|
||
|
||
class Meta:
|
||
model = Board
|
||
fields = [
|
||
'id',
|
||
'board_id',
|
||
'title',
|
||
'description',
|
||
'owner',
|
||
'mentor',
|
||
'student',
|
||
'access_type',
|
||
'participants',
|
||
'background_color',
|
||
'grid_enabled',
|
||
'width',
|
||
'height',
|
||
'is_active',
|
||
'is_template',
|
||
'views_count',
|
||
'elements_count',
|
||
'files_count',
|
||
'snapshot_elements_count',
|
||
'last_edited_by',
|
||
'last_edited_at',
|
||
'elements',
|
||
'created_at',
|
||
'updated_at'
|
||
]
|
||
read_only_fields = [
|
||
'board_id',
|
||
'owner',
|
||
'mentor',
|
||
'student',
|
||
'views_count',
|
||
'elements_count',
|
||
'last_edited_by',
|
||
'last_edited_at',
|
||
'created_at',
|
||
'updated_at'
|
||
]
|
||
|
||
def get_files_count(self, obj):
|
||
"""Получить количество файлов изображений из snapshot."""
|
||
return obj.get_files_count()
|
||
|
||
def get_snapshot_elements_count(self, obj):
|
||
"""Получить количество элементов из snapshot."""
|
||
return obj.get_elements_count_from_snapshot()
|
||
|
||
|
||
class BoardListSerializer(serializers.ModelSerializer):
|
||
"""Сериализатор списка досок (упрощенный)."""
|
||
|
||
owner = UserSerializer(read_only=True)
|
||
mentor = UserSerializer(read_only=True)
|
||
student = UserSerializer(read_only=True)
|
||
last_edited_by = UserSerializer(read_only=True)
|
||
|
||
class Meta:
|
||
model = Board
|
||
fields = [
|
||
'id',
|
||
'board_id',
|
||
'title',
|
||
'description',
|
||
'owner',
|
||
'mentor',
|
||
'student',
|
||
'access_type',
|
||
'background_color',
|
||
'is_active',
|
||
'is_template',
|
||
'views_count',
|
||
'elements_count',
|
||
'last_edited_by',
|
||
'last_edited_at',
|
||
'created_at'
|
||
]
|
||
|
||
|
||
class BoardCreateSerializer(serializers.ModelSerializer):
|
||
"""Сериализатор создания доски."""
|
||
|
||
# mentor и student обязательны для доски типа mentor_student
|
||
mentor = serializers.IntegerField(required=False, allow_null=True)
|
||
student = serializers.IntegerField(required=False, allow_null=True)
|
||
participant_ids = serializers.ListField(
|
||
child=serializers.IntegerField(),
|
||
required=False,
|
||
allow_empty=True
|
||
)
|
||
|
||
class Meta:
|
||
model = Board
|
||
fields = [
|
||
'title',
|
||
'description',
|
||
'mentor',
|
||
'student',
|
||
'access_type',
|
||
'participant_ids',
|
||
'background_color',
|
||
'grid_enabled',
|
||
'width',
|
||
'height',
|
||
'is_template'
|
||
]
|
||
|
||
def validate(self, attrs):
|
||
"""Валидация данных доски."""
|
||
# Для доски типа mentor_student требуются mentor и student
|
||
if attrs.get('access_type') == 'mentor_student':
|
||
if not attrs.get('mentor') or not attrs.get('student'):
|
||
raise serializers.ValidationError(
|
||
'Для доски типа mentor_student требуются поля mentor и student'
|
||
)
|
||
return attrs
|
||
|
||
def create(self, validated_data):
|
||
"""Создание доски."""
|
||
from apps.users.models import User
|
||
|
||
mentor_id = validated_data.pop('mentor', None)
|
||
student_id = validated_data.pop('student', None)
|
||
participant_ids = validated_data.pop('participant_ids', [])
|
||
user = self.context['request'].user
|
||
|
||
# Создаем доску
|
||
board_data = {
|
||
'owner': user,
|
||
**validated_data
|
||
}
|
||
|
||
# Добавляем ментора и студента
|
||
if mentor_id:
|
||
board_data['mentor_id'] = mentor_id
|
||
if student_id:
|
||
board_data['student_id'] = student_id
|
||
|
||
board = Board.objects.create(**board_data)
|
||
|
||
# Добавляем участников
|
||
if participant_ids:
|
||
participants = User.objects.filter(id__in=participant_ids)
|
||
board.participants.set(participants)
|
||
|
||
# Если указаны ментор и студент, добавляем их как участников
|
||
if mentor_id or student_id:
|
||
if mentor_id:
|
||
board.participants.add(User.objects.get(id=mentor_id))
|
||
if student_id:
|
||
board.participants.add(User.objects.get(id=student_id))
|
||
|
||
return board
|
||
|
||
|
||
class BoardSnapshotSerializer(serializers.ModelSerializer):
|
||
"""Сериализатор снимка доски."""
|
||
|
||
created_by = UserSerializer(read_only=True)
|
||
|
||
class Meta:
|
||
model = BoardSnapshot
|
||
fields = [
|
||
'id',
|
||
'board',
|
||
'snapshot_data',
|
||
'created_by',
|
||
'description',
|
||
'created_at'
|
||
]
|
||
read_only_fields = [
|
||
'created_by',
|
||
'created_at'
|
||
]
|
||
|
||
|
||
class BoardSnapshotCreateSerializer(serializers.ModelSerializer):
|
||
"""Сериализатор создания снимка доски."""
|
||
|
||
board_id = serializers.UUIDField(write_only=True)
|
||
|
||
class Meta:
|
||
model = BoardSnapshot
|
||
fields = [
|
||
'board_id',
|
||
'description'
|
||
]
|
||
|
||
def validate_board_id(self, value):
|
||
"""Проверка доски."""
|
||
try:
|
||
board = Board.objects.get(board_id=value)
|
||
except Board.DoesNotExist:
|
||
raise serializers.ValidationError('Доска не найдена')
|
||
|
||
# Проверяем доступ
|
||
user = self.context['request'].user
|
||
if not board.has_access(user):
|
||
raise serializers.ValidationError('У вас нет доступа к этой доске')
|
||
|
||
return value
|
||
|
||
def create(self, validated_data):
|
||
"""Создание снимка."""
|
||
board_id = validated_data.pop('board_id')
|
||
board = Board.objects.get(board_id=board_id)
|
||
user = self.context['request'].user
|
||
|
||
# Собираем данные всех элементов
|
||
elements = board.elements.filter(is_deleted=False)
|
||
elements_data = BoardElementSerializer(elements, many=True).data
|
||
|
||
snapshot_data = {
|
||
'board': BoardSerializer(board).data,
|
||
'elements': elements_data,
|
||
'timestamp': timezone.now().isoformat()
|
||
}
|
||
|
||
snapshot = BoardSnapshot.objects.create(
|
||
board=board,
|
||
created_by=user,
|
||
snapshot_data=snapshot_data,
|
||
**validated_data
|
||
)
|
||
|
||
return snapshot
|