Правильный способ использования DRF и наборов представлений

У меня есть модель:

class Definition(Model):
    definition_id = BigAutoField(primary_key=True)
    definition_name = CharField(max_length=50)

    is_active, created_by, created_datetime, last_modified_by, last_modified_datetime = default_model_attrs()

    class Meta:
        db_table = 'definitions'

    def __str__(self: Self) -> str:
        return self.definition_name

С этим сериализатором:

class DefinitionSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Definition

        fields = [
            'url',
            'definition_id',
            'definition_name',
            'attributes',
            'created_by',
            'created_datetime',
            'last_modified_by',
            'last_modified_datetime',
            'is_active',
        ]

        read_only_fields = [
            'url',
            'definition_id',
            'attributes',
            'created_by',
            'created_datetime',
            'last_modified_by',
            'last_modified_datetime',
            'is_active',
        ]

Я попробовал сделать набор представлений для пары пользовательских действий при создании:

class DefinitionViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows definitions to be viewed or edited.
    """

    queryset = Definition.objects.all().order_by('definition_id')
    serializer_class = DefinitionSerializer
    permission_classes = [permissions.IsAuthenticated]

    def create(self: Self, request: Request, **kwargs: dict[str, Any]) -> Response:
        if not is_valid_db_object_name(request.data['definition_name']):
            return Response(
                {
                    'message': f"Invalid definition name -> {request.data['definition_name']}",
                },
                status=status.HTTP_400_BAD_REQUEST)

        definition = Definition(
            definition_name=request.data['definition_name'],
            created_by=request.user,
            last_modified_by=request.user
        )

        serializer = self.serializer_class(definition,
                                           context={'request': request},
                                           partial=True)

        definition.save()

        return Response(
            data=serializer.data,
            status=status.HTTP_201_CREATED
        )

Но это кажется слишком сложным для проверки поля (is_valid_db_object_name - это, по сути, regex) и для добавления created_by и last_modified_by. Также, пытаюсь понять, как сделать definition_name единственным возможным полем, которое должно передаваться для создания и редактирования. На правильном ли я пути?

Также, как бы выглядел метод редактирования, если бы мне нужно было сделать такую же проверку? На данный момент я просто хочу убедиться, что я на верном пути.

Я использую DRF, потому что мне нужен только API, без интерфейса.

Рекомендуемый путь - обрабатывать большую часть бизнес-логики в сериализаторах, и использовать наборы представлений для отображения действий представления на сериализаторы.

Например, проверка одного поля может быть обработана методом validate_<field> в сериализаторе:

class DefinitionSerializer(serializers.HyperlinkedModelSerializer):

    # Meta class declarations

    def validate_definition_name(self, value):
        if value is not <condition>:
            raise serializers.ValidationError("Invalid definition name")
        return value

    # Additional fields can be set in 'create' method
    def create(self, validated_data):
        instance = Definition(
            **validated_data,
            created_by=self.context['request']['user'],
            last_modified_by=self.context['request']['user']
        )
        return instance

При такой настройке представление может быть упрощено до:

def create(self: Self, request: Request, **kwargs: dict[str, Any]) -> Response:
    serializer = self.serializer_class(data=request.data,
                                       context={'request': request},
                                       partial=True)
    serializer.is_valid()
    serializer.save()

    return Response(
        data=serializer.data,
        status=status.HTTP_201_CREATED
    )
        
    
Вернуться на верх