class Lesson(models.Model):
class Block(PolymorphicModel):
BLOCK_TYPES = (
# Обязательно имена дочерних моделей связанных с этой для поля resource_type в сериализаторе
('InfoBlock', 'Информация'),
('ConditionBlock', 'Условие'),
('QuizBlock', 'Опрос'),
)
lesson = models.ForeignKey(
Lesson, on_delete=models.CASCADE, related_name='blocks', null=True, blank=True)
class InfoBlock(Block):
"""информационный блок"""
sortId = models.PositiveSmallIntegerField(
default=1, verbose_name="Id сортировочный")
transition = models.ForeignKey(Block, null=True, blank=True, on_delete=models.CASCADE,
related_name='infoBlocks',
verbose_name="Блок на который осужествляется переход")
class Meta:
verbose_name = "Информационный блок"
verbose_name_plural = "Информационные блоки"
class ConditionBlock(Block):
"""Блок условие"""
sortId = models.PositiveSmallIntegerField(
default=2, verbose_name="Id сортировочный")
question = models.CharField(max_length=150, verbose_name='Куда дальше?')
class Meta:
verbose_name = "Блок условие"
verbose_name_plural = "Блоки условие"
class ConditionBlockAnswer(models.Model):
""""Ответы для блока условие"""
block = models.ForeignKey(
ConditionBlock, on_delete=models.CASCADE, null=True, blank = True, related_name='answers')
label = models.CharField(max_length=150, verbose_name='Ответ')
transition = models.ForeignKey(Block, null=True, blank=True, on_delete=models.CASCADE, related_name='conditionBlocktransition',
verbose_name="Блок на который осужествляется переход")
class Meta:
verbose_name = "Ответ к блоку условие"
verbose_name_plural = "Ответы к блоку условие"
class QuizBlock(Block):
"""Блок вопрос"""
sortId = models.PositiveSmallIntegerField(
default=3, verbose_name="Id сортировочный")
isShowResult = models.BooleanField(
default=True, verbose_name='Показывать результат ответа')
transitionRight = models.ForeignKey(Block, on_delete=models.CASCADE, null=True, blank=True,
related_name='quizBlockTransitionRight',
verbose_name="Блок на который осужествляется переход Правильно")
transitionError = models.ForeignKey(Block, on_delete=models.CASCADE, null=True, blank=True,
related_name='quizBlockTransitionError',
verbose_name="Блок на который осужествляется переход Ошибка")
class Meta:
verbose_name = "Блок вопрос"
verbose_name_plural = "Блоки вопросов"
class Quiz(models.Model):
""""Вопросы для блока вопроса"""
block = models.OneToOneField(
QuizBlock, on_delete=models.CASCADE, null=True, blank = True, related_name='quiz')
class QuizBlockQuestion(models.Model):
""""Вопросы для блока вопроса"""
quiz = models.ForeignKey(
Quiz, on_delete=models.CASCADE, null=True, blank = True, related_name='questions')
label = models.CharField(max_length=150, verbose_name='Название вопроса')
isMultiply = models.BooleanField(
default=False, verbose_name='Множественный вариант ответов')
class Meta:
verbose_name = "Вопрос к блоку вопрос"
verbose_name_plural = "Вопросы к блоку вопрос"
def __str__(self):
return self.label
class QuizBlockQuestionAnswer(models.Model):
""""Ответы для каждого вопроса из блока вопрос"""
question = models.ForeignKey(
QuizBlockQuestion, on_delete=models.CASCADE, null=True, blank = True, related_name='answers')
label = models.CharField(max_length=150, verbose_name='Ответ')
isRight = models.BooleanField(
default=False, verbose_name='Правильно/Неправильно')
class Meta:
verbose_name = "Ответ к вопросу блока вопрос"
verbose_name_plural = "Ответы к вопросу блока вопрос"
и сериализаторы:
class BlockSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
class Meta:
model = Block
fields = '__all__'
##############################БЛОК информации########################
class InfoBlockSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
files = FileSerializer(many=True, allow_null=True, required=False)
videos = serializers.StringRelatedField(many=True, allow_null=True, required=False)
audios = serializers.StringRelatedField(many=True, allow_null=True, required=False)
images = ImageSerializer(many=True, allow_null=True, required=False)
class Meta:
model = InfoBlock
exclude = ('polymorphic_ctype',)
######################################################################
#########################БЛОК УСЛОВИЕ#################################
class ConditionBlockAnswerSerializer(serializers.ModelSerializer):
class Meta:
model = ConditionBlockAnswer
fields = '__all__'
class ConditionBlockSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
answers = ConditionBlockAnswerSerializer(many=True)
id = serializers.IntegerField(read_only=True)
files = FileSerializer(many=True, allow_null=True, required=False)
videos = serializers.StringRelatedField(many=True, allow_null=True, required=False)
audios = serializers.StringRelatedField(many=True, allow_null=True, required=False)
images = ImageSerializer(many=True, allow_null=True, required=False)
class Meta:
model = ConditionBlock
exclude = ('polymorphic_ctype',)
#######################################################################
######################БЛОК ВОПРОС###################################
class QuizBlockQuestionAnswerSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
class Meta:
model = QuizBlockQuestionAnswer
fields = '__all__'
class QuizBlockQuestionSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
answers = QuizBlockQuestionAnswerSerializer(many=True)
class Meta:
model = QuizBlockQuestion
fields = '__all__'
class QuizSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
questions = QuizBlockQuestionSerializer(many=True)
class Meta:
model = Quiz
exclude = ('block',)
class QuizBlockSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
files = FileSerializer(many=True, allow_null=True, required=False)
videos = serializers.StringRelatedField(many=True, allow_null=True, required=False)
audios = serializers.StringRelatedField(many=True, allow_null=True, required=False)
images = ImageSerializer(many=True, allow_null=True, required=False)
quiz = QuizSerializer()
class Meta:
model = QuizBlock
exclude = ('polymorphic_ctype',)
######################################################################
class BlockPolymorphicSerializer(PolymorphicSerializer, WritableNestedModelSerializer):
resource_type_field_name = 'type'
"""основной полиморфный сериализатор блоков"""
model_serializer_mapping = {
Block: BlockSerializer,
InfoBlock: InfoBlockSerializer,
ConditionBlock: ConditionBlockSerializer,
QuizBlock: QuizBlockSerializer,
}
class Meta:
model = Block
fields = '__all__'
class LessonSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
"""основной сериализатор уроков"""
# при PUT обязательно ставить ID в блоках, иначе id изменится
blocks = BlockPolymorphicSerializer(many=True)
class Meta:
model = Lesson
fields = '__all__'
def to_representation(self, instance):
representation = super().to_representation(instance)
representation['blocksCount'] = instance.blocks.count()
return representation
скинул всё чтоб понимание было, так вот в чём вопрос, если запускаю сериализатор LessonSerializer, то всё нормально сохраняется и отрабатывает, но встала необходимость корректировать отдельно блоки и казалось запуск сериализатора BlockPolymorphicSerializer и всё, но летит ошибка
File "/home/sergey/projects/kviliti/back-drf/venv/lib/python3.10/site-packages/drf_writable_nested/mixins.py", line 235, in _get_save_kwargs
save_kwargs = self._save_kwargs[field_name]
AttributeError: 'QuizBlockSerializer' object has no attribute '_save_kwargs'
причём она идёт только если наследники имеют вложенность, нагуглить удалось только 1 статью но не сработало
https://github.com/beda-software/drf-writable-nest... если кто сталкивался прошу помочь, если в лоб перед строкой ошибки поставить self._save_kwargs = defaultdict(dict) то ошибка пропадает, но ето же не дело лезть в пакет