2016-07-30 6 views
0

私はDRFからチュートリアルを試しています。 私は単に私が私の基本的なUserSerializer持っその後、このdjango rest framework ViewSetアクションごとに必要なフィールドを定義する方法

class User(DefaultUser): 
""" 
Represents a registered User 
""" 
EMAIL_VALIDATOR_LENGTH = 6 

email_validated = models.BooleanField(default=False) 
# using a 6-digit numbers for email validation 
email_validator = models.CharField(
    max_length=6, 
    default=_get_random_email_validator(EMAIL_VALIDATOR_LENGTH), 
    editable=False 
) 
phone_number = models.CharField(validators=[phone_regex], 
           blank=True, null=True, max_length=64) 
# country is required 
country = models.ForeignKey('Country', null=False, blank=False) 
# subdivision is optional 
subdivision = models.ForeignKey('Subdivision', null=True, blank=True) 

ようauth.Userを拡張Userモデルがあります:私のviews.pyで

class UserSerializer(serializers.ModelSerializer): 

class Meta: 
    model = User 
    fields = ('id', 'email', 'password', 'email_validated', 
       'email_validator', 'country', 'subdivision', 'phone_number', 
       'last_login', 'is_superuser', 'username', 'first_name', 
       'last_name', 'is_staff', 'is_active', 'date_joined') 

を、私はUserViewSet持っている:

class UserViewSet(viewsets.ModelViewSet): 
queryset = User.objects.all() 
serializer_class = UserSerializer 

@detail_route(methods=['get', 'post'], url_path='validate-email') 
def validate_email(self, request, pk): 
    user = self.get_object() 
    serializer = UserSerializer(data=request.data) 
    if serializer.is_valid(): 
     user.is_active = True 
     user.save() 
     return Response({'status': 'email validated'}) 
    else: 
     return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 

@detail_route(methods=['post'], url_path='set-password') 
def set_password(self, request, pk): 
    pass 

@list_route() 
def test_list_route(self, request): 
    pass 

問題は、validate_emailでは、実際にはpkしか必要ないのですが、APIをテストするときに、ユーザー名と電子メールも必要であると私に教えてくれました。

私はその後、私のUserSerializer

 extra_kwargs = {'country': {'required': False}, 
        'password': {'required': False}, 
        'username': {'required': False}, 
        } 

に次のコードを追加した今、上記の問題がなくなっているが、私は、ユーザーを作成しようとしたとき、私は実際には、ユーザー名と電子メールを要求したいです。

アクションごとに必要なフィールドを指定する方法はありますか? 例えば、私のset_password()のために、パスワードフィールドが必要です。

おかげで、

答えて

0

は、追加の引数に基づいてフィールドを変更するためにシリアライザのコンストラクタを上書きするようにしてください。それをテストしていないが、それは動作するはずです:あなたが必要とするとき

class UserSerializer(ModelSerializer): 

    def __init__(self, *args, **kwargs): 
     super(UserSerializer, self).__init__(*args, **kwargs) 
     require_password = kwargs.get('require_password', False) 
     require_email = kwargs.get('require_email', False) 

     if require_password: 
      self.fields['password'].required = True 

     if require_email: 
      self.fields['email'].required = True 

はその後require_passwordまたは/およびrequire_email引数を渡す:

serializer = UserSerializer(data=request.data, require_password=True, require_email=True) 
+0

ご返信ありがとうございますが、動作しないと思います。 UserSerializerに次のコードを追加しても、それでもusernameが必要です:self.fields ['username']。require = False –

0

私はそれを自分自身を実装することが判明したので、私は基本的にすべてのフィールドを作りますしかし、アクションでは、デコレータを追加して、リクエスト本体に指定されたキーがあることを確認しました。

デコレータ:それを使用する方法

class AssertInRequest(object): 
""" 
A decorator to decorate ViewSet actions, this decorator assumes the first 
positional argument is request, so you can apply this decorator any methods 
that the first positional argument is request. 

This decorator itself takes a list of strings as argument, and will check 
that the request.data.dict() actually contains these keys 

For example, if you have a action to set user password which you expect that 
in the request body should have 'password' provided, use this decorator for 
the method like 

@detail_route() 
@AssertInRequest(['password']) 
def set_password(self, request, pk): 
    pass 
""" 

def __init__(self, keys): 
    self.keys = [] 
    for key in keys: 
     if hasattr(key, 'upper'): 
      self.keys.append(key.lower()) 

def __call__(self, func): 
    def wrapped(*args, **kwargs): 
     if self.keys: 
      try: 
       request = args[1] 
      except IndexError: 
       request = kwargs['request'] 
      if request: 
       json_data = get_json_data(request) 
       for key in self.keys: 
        if key not in json_data or not json_data[key]: 
         return DefaultResponse(
          'Invalid request body, missing required data [%s]' % key, 
          status.HTTP_400_BAD_REQUEST) 
     return func(*args, **kwargs) 

    return wrapped 

@detail_route(methods=['post'], url_path='set-password', permission_classes=(IsAuthenticated,)) 
@AssertInRequest(['password']) 
def set_password(self, request, pk): 
    user = self.get_object() 
    json_data = get_json_data(request) 
    user.set_password(json_data['password']) 
    user.save() 
    return DefaultResponse(_('Successfully set password for user %s' 
          % user.email), status.HTTP_200_OK) 

私はそれが今のエレガントが、私にとっては、おそらく十分ではありませんね。

関連する問題