2

我正在開發使用Django REST Framework和Angular 4的應用程序。
我不知道UPDATE登錄用戶信息時令牌的處理方式。

如何使用Django REST框架更新USERNAME_FIELD時的標記

Django的所述的用戶模型如下被定製。
登錄密鑰從用戶名更改爲電子郵件。

[models.py]

class Account(AbstractBaseUser): 
    username = models.CharField(_('username'), max_length=30, unique=True) 
    first_name = models.CharField(_('first name'), max_length=30, blank=True) 
    last_name = models.CharField(_('last name'), max_length=30, blank=True) 
    email  = models.EmailField(verbose_name='email address', max_length=255, unique=True) 
    profile  = models.CharField(_('profile'), max_length=255, blank=True) 
    is_active = models.BooleanField(default=True) 
    is_staff = models.BooleanField(default=False) 
    is_admin = models.BooleanField(default=False) 
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now) 

    objects = AccountManager() 
    USERNAME_FIELD = 'email' 
    REQUIRED_FIELDS = ['username'] 

    def user_has_perm(user, perm, obj): 
     return _user_has_perm(user, perm, obj) 

    def has_perm(self, perm, obj=None): 
     return _user_has_perm(self, perm, obj=obj) 

    def has_module_perms(self, app_label): 
     return self.is_admin 

    def get_short_name(self): 
     return self.first_name 

    @property 
    def is_superuser(self): 
     return self.is_admin 

    class Meta: 
     db_table = 'api_user' 
     swappable = 'AUTH_USER_MODEL' 

更新來自角4的用戶信息的功能如下實現。
將新用戶信息放入帶有函數updateUserInfo的Django REST框架中。

[component.ts]

updateUserInfo() { 
    this.authService.updateUserInfo({ 
    email: this.editUserEmail, 
    username: this.editUserName, 
    profile: this.edtiUserProfile 
    }) 
    .subscribe(
    data => { 
     this.updateSuccessMessage = "success userinfo update"; 
     this.updateErrorMessage = null; 
     this.authService.userInfo; 
    }, 
    error => { 
     this.updateErrorMessage = "failed userinfo update"; 
     this.updateSuccessMessage = null; 
    } 
); 
} 

[service.ts]

updateUserInfo(userUpdateInfo) { 
    return this.http 
    .put(this.UpdateUserUrl, 
     userUpdateInfo, 
     this.jwt() 
    ); 
} 

jwt() { 
    if (this.LoginToken) { 
    let headers = new Headers({ 'Content-Type': 'application/json', 'Authorization': 'JWT ' + this.LoginToken.token }); 
    return new RequestOptions({ headers: headers }); 
    } 
} 

用於在Django更新用戶信息的視圖和串行器如下。

[views.py]

class AuthInfoUpdateView(generics.UpdateAPIView): 
    permission_classes = (permissions.IsAuthenticated,) 
    serializer_class = AccountSerializer 
    lookup_field = 'email' 
    queryset = Account.objects.all() 

    def get_object(self): 
     try: 
      instance = self.queryset.get(email=self.request.user) 
      return instance 
     except Account.DoesNotExist: 
      raise Http404 

[serializers.py]

class AccountSerializer(serializers.ModelSerializer): 
    password = serializers.CharField(write_only=True, required=False) 

    class Meta: 
     model = Account 
     fields = ('id', 'username', 'email', 'profile', 'password') 

    def create(self, validated_data): 
     return Account.objects.create_user(request_data=validated_data) 

    def update(self, instance, validated_data): 
     if 'password' in validated_data: 
      instance.set_password(validated_data['password']) 
     else: 
      instance = super().update(instance, validated_data) 
     instance.save() 
     return instance 

,現在正在發生的問題更新電子郵件時的行爲。
由於USERNAME_FIELD是一封電子郵件,因此更新電子郵件必須更新前端持有的令牌。
但我不知道如何獲得新的電子郵件令牌。

回答

1

我認爲保持用戶身份驗證的唯一方法是生成一個新的令牌並將其發回,我不知道用django-rest-framework-jwt來執行此操作的另一種方法。

要做到這一點,你需要定製您的AuthInfoUpdateViewput方法:

def put(self, request, *args, **kwargs): 
    serializer = self.serializer_class(self.get_object(), data=request.data, partial=True) 

    if serializer.is_valid(): 
     instance = serializer.save() 
     # Generate a new token 
     payload = jwt_payload_handler(instance) 
     token = jwt.encode(payload, settings.SECRET_KEY) 
     response = JsonResponse({'token': token.decode('unicode_escape')}) 
     response.status = 200 
     return response 
    else: 
     response = JsonResponse({'errors': serializer.errors}) 
     response.status = 500 
     return response 

至於爲這個簡單的,那麼你只需要更新您的前端令牌不提示用戶再次登錄。

希望這會有所幫助!