我不太清楚如何在DRF中实现序列化器和视图的方法:
我有一个扩展了AbstractBaseUser的账户模型。视图集如下所示:
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.")
在视图的create方法中,它会检查序列化器是否有效,然后保存它并根据结果返回响应。我的第一个问题是,序列化器的create()方法何时被调用?在我看来,该方法直接被调用视图的create()方法中调用的create_user(模型方法)绕过了。它是否被调用了?有什么意义吗?
第二个问题是,在update方法中返回状态码遇到麻烦,实例已在序列化器中保存。如果验证失败,序列化器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)
我非常需要澄清一些事情。我不确定如何请求视图/序列化器方法的流,并且不确定如何在序列化器中保存实例并同时决定在视图中返回哪个响应。
编辑:
我删除了 AccountViewSet 的 create 和 update 方法,并修复了 get_permissions,按照您的建议,我还添加了用户名验证到 validate 中。我还更新了序列化器的 create 和 update 方法,以下是新版本:
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
不是已经为新用户设置了密码吗?另外,在create
和update
视图中没有代码会出现问题吗?如果没有视图代码,serializer.save()
何时被调用?serializer.validate
何时运行而不需要调用serializer.is_valid()
?