使用Django API rest fram更新用户错误

2024-05-28 19:30:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我无法更新用户,因为Django在postman中给了我这个错误:

AttributeError at /profesionales/
Got AttributeError when attempting to get a value for field `user` on serializer `ProfesionalesSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `User` instance.
Original exception text was: 'User' object has no attribute 'user'.

Request Method: PUT
Request URL: http://127.0.0.1:8000/profesionales/
Django Version: 1.11.6
Python Executable: C:\Users\Ismael\AppData\Local\Programs\Python\Python36\python.exe
Python Version: 3.6.3

这是我的代码:

视图.py

^{pr2}$

序列化程序.py

class UserSerializer(serializers.Serializer):

    username = serializers.CharField()
    first_name = serializers.CharField(allow_blank=True)
    last_name = serializers.CharField(allow_blank=True)
    email = serializers.CharField(allow_blank=True)

    class Meta:
        fields = ('username', 'first_name', 'last_name', 'email')

        def create(self, validated_data):
            user = User.objects.create(**validated_data)
            return user

class ProfesionalesSerializer(serializers.Serializer):

    user = UserSerializer()
    numColegiado = serializers.CharField(allow_blank=False)

    class Meta:
            fields = ('user', 'numColegiado')

    def create(self, validated_data):
        user_data = validated_data.pop('user')
        user = User.objects.create(**user_data)
        profesional = Profesionales.objects.create(user=user, **validated_data)

        return profesional

    def update(self, instance, validated_data):

        num_colegiado = validated_data.get('numColegiado')
        user_data = validated_data.pop('user')
        user = User.objects.get(**user_data)

        profesionales = user.profesionales

        if num_colegiado:
            profesionales.numColegiado = num_colegiado
            profesionales.save()
        return instance

模型.py

class Profesionales(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    dni = models.CharField(max_length=9, blank=True, default='')
    numColegiado = models.CharField(max_length=8, blank=True, default='')
    valoracionMedia = models.FloatField(blank=True, default=0)
    numVotos = models.IntegerField(blank=True, default=0)

    def __str__(self):
        return self.numColegiado

Tags: nameselftruedatamodelscreateclasscharfield
2条回答

好吧,我知道了-但是说实话,你应该重新考虑你的API设计。在

问题是-没有问题-我的意思是从你的代码我不能重现错误。我可能假设用户模型-如果您可以粘贴用户模型定义将是很好的(或者如果这是一个标准的django用户-也要提到这一点)。在

因此,首先我要将序列化程序更改为模型序列化程序:

序列化程序.py

class UsernameValidator(object):

    def set_context(self, serializer_field):
        """
        This hook is called by the serializer instance,
        prior to the validation call being made.
        """
        # Determine the existing instance, if this is an update operation.
        self.instance = getattr(serializer_field.parent, 'instance', None)
        if not self.instance:
            # try to get user from profesionales:
            root_instance = getattr(serializer_field.root, 'instance', None)
            self.instance = getattr(root_instance, 'user', None)

    def __call__(self, value):
        if self.instance and User.objects.filter(username=value).exclude(id=self.instance.id).exists():
            raise ValidationError('Username already exists.')

        if not self.instance and User.objects.filter(username=value).exists():
            raise ValidationError('Username already exists.')


class UserSerializer(serializers.ModelSerializer):

    username = serializers.CharField(max_length=128, validators=[UsernameValidator()])

    class Meta:
        model = User
        fields = ('username', 'first_name', 'last_name', 'email')


class ProfesionalesSerializer(serializers.ModelSerializer):

    user = UserSerializer()
    numColegiado = serializers.CharField(allow_blank=False)

    class Meta:
        model = Profesionales
        fields = ('user', 'numColegiado')

    def create(self, validated_data):
        user_data = validated_data.pop('user')
        user = User.objects.create(**user_data)
        profesional = Profesionales.objects.create(user=user, **validated_data)
        return profesional

    def update(self, instance, validated_data):
        user_data = validated_data.pop('user')
        user = instance.user
        userSerializer = UserSerializer(user, data=user_data)
        if userSerializer.is_valid(raise_exception=True):
            userSerializer.save()

        num_colegiado = validated_data.get('numColegiado')
        if num_colegiado:
            instance.numColegiado = num_colegiado
            instance.save()
        return instance

正如您所注意到的-我添加了UsernameValidator,这对于API正常工作非常重要0-它基本上是搜索现有的用户实例并检查用户名是否存在

我还更改了update方法—现在它使用的是UserSerializer explicite;还纠正了一些错误—返回已验证的\u data而不是instance等等。在

最后视图.py

^{pr2}$

我缩短了代码-使用中的引发异常是有效的方法。在

实际上-很抱歉没有遵循stackoverflow规则-也没有为您的实际问题提供答案-但我坚信,通过分析示例,您可以找到答案。如果你还有任何问题-请问。在

在您的类ProfesionalesSerializer上,您已经将user定义为UserSerializer的实例。相反,user应该是一个字段。不能将序列化程序用作“字段”。在

编辑:忽略这个。结果你可以。请看这里:http://www.django-rest-framework.org/api-guide/serializers/#dealing-with-nested-objects

(感谢@opalczynski)

相关问题 更多 >

    热门问题