2014-12-21 3 views
13

상황추가 시리얼 필드 장고 REST 프레임 워크 3

I는 사용자의 창조를 위해 할 수있는 간단한 엔드 포인트를 작성하고 있습니다. 내 사용자 모델에없는 입력란 (예 : confirm_password)이 필요합니다. 이 필드와 내 모델에있는 다른 필드를 비교하는 유효성 검사를 실행 한 다음 serializer에서 추가 필드를 사용하지 마십시오.

문제

DRF 버전 3이를 달성하기위한 프로세스를 변경, 나는 꽤 문서 내가 할 제안 무엇인지 이해하지 않습니다. 설명서는 here을 참조하십시오. 나는이처럼 보이는 UserSerializer을 만든

솔루션에서

시도 : 나는 validateconfirm_password 터지는 것은 내 문제를 돌봐하지만, 난 그냥 얻을 것이라고 기대했다

from django.contrib.auth import get_user_model 
from rest_framework import serializers 

class UserSerializer(serializers.ModelSerializer): 
    confirm_password = serializers.CharField(allow_blank=False) 

    def validate(self, data): 
     """ 
     Checks to be sure that the received password and confirm_password 
     fields are exactly the same 
     """ 
     if data['password'] != data.pop('confirm_password'): 
      raise serializers.ValidationError("Passwords do not match") 
     return data 

    def create(self, validated_data): 
     """ 
     Creates the user if validation succeeds 
     """ 
     password = validated_data.pop('password', None) 
     user = self.Meta.model(**validated_data) 
     user.set_password(password) 
     user.save() 
     return user 

    class Meta: 
     # returns the proper auth model 
     model = get_user_model() 
     # fields that will be deserialized 
     fields = ['password', 'confirm_password', 
        'username', 'first_name', 'last_name', 'email'] 
     # fields that will be serialized only 
     read_only_fields = ['is_staff', 'is_superuser'] 
     # fields that will be deserialized only 
     write_only_fields = ['password' 'confirm_password'] 

다음 :

Got KeyError serializer의 confirm_password 필드 값은 UserSerializer입니다. 나는 당신의 비밀번호 확인을 표시하지 않습니다 있으리라 믿고있어 같이 시리얼 필드는, 당신은 쓰기 전용 필드 찾고있는 OrderedDict 예를

+0

그냥 머리까지, 그것은 일반적입니다 serializer 상단에 'Meta'클래스가 있는데, 일반적으로 찾고있는 대부분의 정보가 들어 있기 때문입니다. –

+0

아, 그건 이해가됩니다. 감사합니다! – nmagerko

답변

18

에 어떤 속성이나 키와 일치 잘못이 아닌 이름이 될 수 있습니다 API Django REST Framework는 read_only 매개 변수를 보완하기 위해 2.3.x 타임 라인에 write_only 매개 변수를 도입 했으므로 업데이트를 수행하는 경우에만 시간 확인이 실행됩니다. write_only_fields 메타 속성이 같은시기에 추가되었지만이 두 가지가 함께 작동하는 방식을 이해하는 것이 중요합니다. 이 자동으로 생성 될 때

write_only_fields 메타 속성은 자동으로 User 모델에 password 필드와 같은 필드에 write_only 속성을 추가합니다. 이 모델에없는 필드 또는 serializer에 명시 적으로 지정된 필드에 대해이 작업을 수행하지 않습니다. 귀하의 경우 serializer에서 confirm_password 필드를 명시 적으로 지정하고 있으므로 이것이 작동하지 않습니다. 있어 KeyError

시리얼 UserSerializer에 필드 confirm_password의 값을 얻기 위해 시도. 시리얼 라이저 필드는 당신의 confirm_password 필드를 직렬화하려고하면, OrderedDict 예를

이가 만든 사용자의 재 직렬화시에 발생에 어떤 속성이나 키와 일치 잘못이 아닌 이름이 될 수 있습니다. User 모델에서 필드를 찾을 수 없기 때문에이 오류를 트리거하여 문제를 설명합니다. 죄송 합니다만 사용자이므로 User 인스턴스 대신 OrderedDict 인스턴스를 혼란스럽게 보게됩니다.

class UserSerializer(serializers.ModelSerializer): 
    confirm_password = serializers.CharField(allow_blank=False, write_only=True) 

명시 적으로 시리얼 필드에 write_only을 지정하고 당신이 기대하는 행동을 볼 수, 당신의 write_only_fields에서 필드를 제거합니다.

당신은 루트 모델을 직접 가지고 사용하려는 필드에 액세스하지 않습니다 중첩 된 시리얼 구현을 나타내는 모델 또한 유용이 link

0

에 이에 대한 설명서를 찾을 수 있습니다. 가 @vyscond 주셔서 감사합니다, 은 참고로 여기에 제 경우입니다) : 대부분의 사람들이 넣어 위해

models.py

class Company(models.Model): 
    permission_classes = (
     IsCompanyMember, 
    ) 

    name = models.CharField(
     unique=True, 
     max_length=100, 
     verbose_name='company name', 
     null=False 
    ) 
class Profile(models.Model): 

    company = models.ForeignKey(Company, on_delete=models.CASCADE, null=True) 
    user = models.OneToOneField(User, on_delete=models.CASCADE) 
    is_company_admin = models.BooleanField(default=False, null=False) 
    is_email_validated = models.BooleanField(default=False, null=False) 
    is_approved_by_company_admin = models.BooleanField(default=False, null=False) 

serializer.py

class CompanySerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Company 
     fields = ('name',) 

class CustomUserRegistrationSerializer(serializers.ModelSerializer): 
    password = serializers.CharField(style={'input_type': 'password'}, 
           write_only=True, 
           validators=settings.get('PASSWORD_VALIDATORS')) 

    company = CompanySerializer(allow_null=False, required=True,write_only=True) 

    class Meta: 
     model = User 
     fields = ('username', 
        'email', 
        'password', 
        'company', 
        'first_name', 
        'last_name') 
관련 문제