Правильный способ использования 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
)