Я запутался, как реализовать методы в сериализаторах и взглядах в ФПИ:Джанго Rest Рамочных сериализаторы и просмотры
У меня есть модель счета простирающейся AbstractBaseUser. Viewset выглядит следующим образом:
class AccountViewSet(viewsets.ModelViewSet):
lookup_field = 'username'
queryset = Account.objects.all()
serializer_class = AccountSerializer
def get_permissions(self):
if self.request.method in permissions.SAFE_METHODS:
return (permissions.AllowAny(), TokenHasReadWriteScope())
if self.request.method == 'POST':
return (permissions.AllowAny(), TokenHasReadWriteScope())
return (permissions.IsAuthenticated(), IsAccountOwner(), TokenHasReadWriteScope())
def create(self, request):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
Account.objects.create_user(**serializer.validated_data)
return Response(serializer.validated_data, status=status.HTTP_201_CREATED)
return Response({
'status': 'Bad request',
'message': 'Account could not be created with received data.'
}, status=status.HTTP_400_BAD_REQUEST)
сериализатор так:
class AccountSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True, required=False)
confirm_password = serializers.CharField(write_only=True, required=False)
class Meta:
model = Account
fields = ('id', 'email', 'username', 'created_at', 'updated_at',
'first_name', 'last_name', 'tagline', 'password',
'confirm_password',)
read_only_fields = ('created_at', 'updated_at',)
def create(self, validated_data):
return Account.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.username = validated_data.get('username', instance.username)
instance.save()
password = validated_data.get('password', None)
confirm_password = validated_data.get('confirm_password', None)
if password and confirm_password:
instance.set_password(password)
instance.save()
update_session_auth_hash(self.context.get('request'), instance)
return instance
def validate(self, data):
if data['password'] and data['confirm_password'] and data['password'] == data['confirm_password']:
try:
validate_password(data['password'], user=data['username']):
return data
except ValidationError:
raise serializers.ValidationError("Password is not valid.")
raise serializers.ValidationError("Passwords do not match.")
О методе создания для представления, он проверяет, является ли сериализатор действителен, то сохраняет его и возвращает ответы в зависимости от результата , Мой первый вопрос: когда вызывается метод serializer create()? Мне кажется, что метод вообще обходит метод вызова create_user (модельный метод) в методе create(). Вызывается ли это вообще? В чем смысл этого?
Во-вторых, у меня возникли проблемы с возвратом кода состояния из метода обновления, экземпляр сохраняется в сериализаторе. Будет ли код внутри serializer update() работать, если проверка не выполняется?
Вот то, что я до сих пор:
def update(self, request, pk=None):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
<< what goes here??? >>
return Response(serializer.validated_data, status=status.HTTP_200_OK)
except serializers.ValidationError as e:
return Response({
'status': 'Bad request',
'message': str(e)
}, status=status.HTTP_400_BAD_REQUEST)
return Response({
'status': 'Bad request',
'message': 'Account could not be updated with received data.'
}, status=status.HTTP_400_BAD_REQUEST)
я отчаянно нуждаются в уточнении. Я не уверен, как запрашивать потоки через методы view/serializer, и я не уверен, как я могу сохранить экземпляр в сериализаторе и решить, какой ответ будет возвращать в представлении одновременно.
EDIT:
я удалил create
и update
методы и фиксированную get_permissions
для AccountViewSet
и я добавил проверку имени пользователя в validate
, как вы предложили. Я также обновил сериализатор создавать и методы обновления, вот новые версии:
def create(self, validated_data):
instance = super(AccountSerializer, self).create(validated_data)
instance.set_password(validated_data['password'])
instance.save()
return instance
def update(self, instance, validated_data):
instance.username = validated_data.get('username', instance.username)
password = validated_data.get('password', None)
confirm_password = validated_data.get('confirm_password', None)
if password and confirm_password:
instance.set_password(password)
instance.save()
update_session_auth_hash(self.context.get('request'), instance)
else:
instance.save()
return instance
Мои только вопросы это необходимо вызвать set_password
после create
? Does't create
задать пароль для нового пользователя? И нормально ли иметь код в представлении для create
и update
? Где serializer.save()
вызывается без кода просмотра и когда выполняется сериализатор validate
без вызова serializer.is_valid()
?
Я редактировал вопрос, чтобы включить изменения, которые вы предложили, и еще несколько небольших вопросов о предлагаемых вами изменениях. - Не задано ли set_password создавать? Без кода просмотра сериал.save() и serializer.is_valid() все равно вызываются и когда? Если нет, когда вы вызываете update/create/validate? – shenk
Последний вопрос: следует ли задавать поле id как readonly в мета для сериализатора? Или где-то еще. – shenk
Я проверил источник django, set_password не вызывается во время создания или обновления, но его можно вызвать до формы .save(), а затем установка нового пароля будет включена в общую форму .save() – Jerzyk