Интересный вопрос, и хорошо поставленный.
Использование SlugRelatedField('state__label', queryset=...)
работает нормально, с 1 предупреждением: просто вызывается queryset.get(state__label="x")
, что приводит к ошибкам, если нет точного 1 совпадения.
1 ) Напишите произвольное поле?
Наследовать от SlugRelatedField
и переопределить to_internal_value()
, возможно, вызвав .first()
вместо .get()
или любой другой лог c, который вам нужен.
2) Переоцените это отношение, может быть, его 1 к 1? поле выбора?
Я немного озадачен тем, как все это будет работать, поскольку вы можете иметь «1 ко многим» с State
=> ReviewState
. По умолчанию поиск (если вы не делаете # 1) выдаст ошибку, когда происходит несколько совпадений.
Может быть, это ситуация 1 к 1 с моделью? Возможно, ReviewState может использовать ChoiceField
вместо таблицы состояний?
Возможно, «меткой» может быть PK таблицы State
, а также SlugField
вместо неуникального CharField
?
3) Писать разные сериализаторы для случаев List
и Create
DRF не дает нам встроенного способа сделать это, но это опора на «один сериализатор, чтобы сделать все это» является причиной многих проблем, которые я вижу в SO. Просто очень трудно получить то, что вы хотите, не имея разных сериализаторов для разных случаев. Сделать это не сложно, но вот пример, использующий переопределение:
from rest_framework import serializers as s
class MyCreateSerializer(s.ModelSerializer):
state = s.SlugRelatedField(...)
...
class MyListSerializer(s.ModelSerializer):
# use dotted notation, serializers read *object* attributes
state = s.CharField(source="state.state.label")
...
class MyViewSet(ModelViewSet):
queryset = MyModel.objects.select_related('state__state')
...
def get_serializer_class(self):
if self.action == "create":
return MyCreateSerializer
else:
return MyListSerializer