【问题标题】:How to update fields of custom user model using Django serializer如何使用 Django 序列化程序更新自定义用户模型的字段
【发布时间】:2020-04-20 07:52:53
【问题描述】:

当用户想要更新之前创建的用户模型时,我正在尝试更新用户模型的各个字段。我有一个自定义用户模型,并且我正在使用 django rest 框架来更新 api。

views.py

class UserUpdate(generics.UpdateAPIView):
    """
    Update user.
    """
    parser_class = (FileUploadParser,)
    permission_classes = (AllowAny,)
    queryset = User.objects.all()
    serializer_class = UserUpdateSerializer

    def update(self, request, *args, **kwargs):
        instance = self.get_object()
        instance.user_id = request.data.get("user_id")
        instance.save()
        serializer = self.get_serializer(instance, data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        return Response(serializer.data)

models.py

class User(models.Model):
    USER_CHOICES = (
        (1, u'ADMIN'),
        (2, u'SALES'),
        (3, u'KITCHEN'),
        (4, u'EMPLOYEE'),
    )
    image = models.ImageField(upload_to='employees/', null = True, blank = True)
    name = models.CharField(max_length=50)
    user_id = models.CharField(max_length=30, primary_key = True, blank = False)
    email = models.CharField(max_length=50)
    password = models.CharField(max_length=100)
    is_active = models.BooleanField(default=True)
    user_group = models.PositiveSmallIntegerField(default=4, choices=USER_CHOICES)
    firebase_token = models.CharField(max_length=150, default=None, null = True)
    shop =  models.ForeignKey(Shop, on_delete=models.SET_DEFAULT, default=None)
    phone = PhoneField(blank=False, default=0)

serializers.py

class UserUpdateSerializer(serializers.ModelSerializer):
    shop = serializers.CharField()
    class Meta:
        model = User
        fields = ('image', 'url', 'phone', 'name', 'user_id','email', 'password', 'is_active', 'user_group', 'shop')

    def update(self, instance, validated_data):
        shop = validated_data.pop('shop')
        user_id = validated_data.pop("user_id")
        print(user_id)
        shopId = Shop.objects.filter(name=shop).values('shop_id').first()
        if shopId is not None:
            shop_id = shopId['shop_id']
            try:
                if user_id is not None:
                    instance.name = validated_data.get('name', instance.name)
                    instance.image = validated_data.get('image', instance.image)
                    instance.email = validated_data.get('email', instance.email)
                    instance.phone = validated_data.get('phone', instance.phone)
                    instance.password = validated_data.get('password', instance.password)
                    instance.user_group = validated_data.get('user_group', instance.user_group)
                    instance.shop_id = validated_data.get('shop_id', instance.shop_id)
                    instance.is_active =  True
                    instance.save()
                    return instance
                else:
                    print("Test")
            except Exception as e:
                return e
        else:
            return None

这是抛出一个错误,提示用户已经存在!

请帮忙!

【问题讨论】:

  • 我不是专家,但您尝试在视图的更新方法中更新主键“user_id”对我来说似乎很奇怪。我猜它不喜欢你试图保存更改或其他东西。虽然可能是错的。希望对您有所帮助。
  • @clintsmith 很抱歉,我删除了同样的内容,但仍然存在同样的问题。

标签: django django-rest-framework django-serializer drf-queryset


【解决方案1】:

当您调用UserUpdate API 时,它将为每个新的user_id 创建每个新的User。 我不知道你为什么要更新user_id。任何新的user_id 都会创建一个新的User 实例。 如果要更新user_id以外的内容,则需要删除以下行。

  1. UserUpdate API 视图中删除这些行。

    instance.user_id = request.data.get("user_id")       
    instance.save()
    
  2. UserUpdateSerializer中删除这一行

    instance.user_id = validated_data.get('user_id', instance.user_id)
    
  3. lookup_field = 'user_id' 添加到UserUpdate API 视图

  4. 在网址添加user_id,如

    path('userupdate/<str:user_id>/', UserUpdate.as_view())
    

【讨论】:

  • 我的 user_id 是字符串类型,我将其更改为 。我以前没有使用过相同的,我正在尝试使用这些 URL 对其进行测试。 MY_IP/userupdate/id/tt12345/ MY_IP/userupdate/tt12345/ 这两个都显示Url Not Found。
  • 更新了答案。 MY_IP/userupdate/{user_id}/ 应该可以工作。
  • 很抱歉,它仍然无法正常工作。在 /userupdate/{tt12345}/ 找不到页面
  • 我已经将 {user_id} 标识为占位符而不是字符串。所以,删除 {},试试 /userupdate/tt12345/
【解决方案2】:

只需像下面这样更改您的序列化程序

class UserUpdateSerializer(serializers.ModelSerializer):
    shop = serializers.CharField()

    class Meta:
        model = User
        fields = ('image', 'url', 'phone', 'name', 'user_id','email', 'password', 'is_active', 'user_group', 'shop')

    def update(self, instance, validated_data):
        shop = validated_data.pop('shop')
        shop_obj = Shop.objects.filter(name=shop).first()
        if shop_obj:
            instance.shop = shop_obj
        return super().update(instance, validated_data)

【讨论】:

  • 当我使用 POST 方法时,它会抛出一个错误,说 Method Not Allowed: /userupdate/
  • @RajuIn 你应该使用PUT 方法进行更新。要创建你应该使用POST 方法
  • 兄弟,我收到此错误。AssertionError:预期视图 UserUpdate 将使用名为“pk”的 URL 关键字参数调用。修正您的 URL 配置,或正确设置视图上的 .lookup_field 属性。
  • 您应该在发送 PUT 请求时在 url 中传递 pk,例如 /userupdate/10/ 其中 10 是用户 pk
  • 您不需要显式创建用户 ID。 Django 自动生成一个id 字段。可以参考learnbatta.com/blog/using-custom-user-model-in-django-23了解django模型的使用方法
猜你喜欢
  • 1970-01-01
  • 2019-04-28
  • 2016-08-08
  • 2019-01-17
  • 1970-01-01
  • 2021-11-30
  • 2014-03-01
  • 2015-07-24
  • 2018-02-04
相关资源
最近更新 更多