Django Rest Framework 序列化器和 View

标签 django serialization django-rest-framework

我很困惑如何在 DRF 中的序列化器和 View 中实现方法:

我有一个扩展 AbstractBaseUser 的帐户模型。 View 集如下所示:

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.")

在 View 的 create 方法中,它检查序列化程序是否有效,然后保存它并根据结果返回响应。我的第一个问题是何时调用序列化程序 create() 方法?在我看来,通过在 View 的 create() 方法中调用 create_user (模型方法)似乎完全绕过了该方法。它会被调用吗?拥有它有什么意义?

其次,我无法从更新方法返回状态码,实例保存在序列化程序中。如果验证失败,序列化程序 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 /序列化器方法请求流,我不确定如何将实例保存在序列化器中并决定同时在 View 中返回哪个响应。

编辑:

我删除了 createupdate方法和固定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 之后?不 create为新用户设置密码? create 的 View 中没有代码可以吗?和 update ? serializer.save() 在哪里在没有 View 代码的情况下被调用,序列化程序何时 validate无需调用 serializer.is_valid() 即可运行?

最佳答案

在您的 create() AccountViewSet 中的方法类,你正在创建 Account序列化程序验证通过时的实例。相反,您应该调用 serializer.save() .

如果你看看 save() BaseSerializer 中的方法你会看到它调用了 create()update()方法,取决于是创建还是更新模型实例。因为你没有调用 serializer.save()AccountViewSet.create()方法,AccountSerializer.create()方法没有被调用。希望这能回答你的第一个问题。

您的第二个问题的答案也是缺少 serializer.save() .替换 << what goes here??? >>serializer.save() .这(正如我上面解释的)将调用 AccountSerializer.update()方法。

关于Django Rest Framework 序列化器和 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37537974/

相关文章:

django - 我如何过滤与类别有多对多关系的变体

python - 迭代 Django 表单结果(不在模板中)

javascript - Node.js:如何序列化/反序列化 React 组件?

performance - 如何在 Haskell 中进行快速数据反序列化

python - 将 networkx DiGraph 打印为嵌套的 JSON 格式

python - Django Rest Framework-有效地检索反向外键的相关字段

django - Django ViewSet中detail参数的含义是什么?

python - 提交表单时出现 Django IntegrityError (在 View 中预填充)

python - Django:无法导入名称 formset_factory

django - 在保存之前将数据添加到 Django 表单?