検証

2017-02-13 4 views
1

は、次検証

class ProfessionalQualification(Log_Active_Owned_Model_Mixin): 

    PROF_TEACHER = 1 
    PROF_ENGINEER = 2 
    PROF_DOCTOR  = 4 
    PROF_PROFESSOR = 8 
    PROF_MANAGER = 16 
    PROF_CLERK  = 32 
    PROF_SALESMAN = 64 
    PROF_BUSINESSMAN= 128 
    PROF_OTHER  = 129 

    VALID_PROFESSIONS = (
     (PROF_TEACHER,  "Teacher" ), 
     (PROF_ENGINEER,  "Engineer" ), 
     (PROF_DOCTOR,  "Doctor" ), 
     (PROF_PROFESSOR, "Professor"), 
     (PROF_MANAGER,  "Manager" ), 
     (PROF_CLERK,  "Clerk" ), 
     (PROF_SALESMAN,  "Salesman" ), 
     (PROF_BUSINESSMAN, "Businessman"), 
     (PROF_OTHER,  "Other" ) 
    ) 

    profession_type   = IntegerField(choices=VALID_PROFESSIONS, null=False, blank=False) 
    profession_type_name = CharField(max_length=60, null=True, blank=True) 
    institue    = CharField(max_length=160, null=False, blank=False) 
    address     = ForeignKey(to=City, null=False) 
    year_start    = CurrentYearField(null=False, blank=False) 
    in_progress    = BooleanField(null=False, blank=False) 
    year_end    = CurrentYearField(null=True, blank=True) 

私のモデルの定義であるIは、シリアライザレベルで検証を行うシリアライザにvalidate()メソッドを定義している私のシリアライザ

class ProfQualSerializer(OwedModelSerializerMixin, ModelSerializer): 

    #address = ConcreteAddressSerializer() 
    class Meta: 
     model = UserProfessionalQual 
     fields = (
        "profession_type", "profession_type_name", \ 
        "institue", "address", "year_start", 
        "in_progress", "year_end" 
       ) 

    def validate(self, dict_input): 
     errors = defaultdict(list) 
     profession_type = dict_input["profession_type"] 

     if profession_type == UserProfessionalQual.PROF_OTHER: 
      try: 
       RestAPIAssert(dict_input.get("profession_type_name", None), 
           "Profession-type-name must be passed, for other type of profession", 
           log_msg="Profession-type-name not passed", exception=ValidationError) 

      except ValidationError as e: 
       errors["profession_type"].append(str(e)) 

     year_start = dict_input["year_start"] 
     year_end = dict_input.get("year_end", None) 
     in_progress = dict_input.get("in_progress", None) 

     request  = self._context["request"] 
     user_dob = request.user.dob 
     age   = request.user.age 

     current_time = datetime.datetime.now() 
     if not user_dob: 
      user_dob = relativedelta(current_time, years=age) 

     if year_start < user_dob.year: 
      errors["year_start"].append("Year-start can't be before user's DOB") 

     elif year_start > year_end: 
      errors["year_start"].append("Year-end can't be before year-start") 

     elif year_end > current_time.year: 
      dict_input["in_progress"] = True 

     else: 
      # if user have not passed in_progress flag, then 
      # set it false. 
      if dict_input.get("in_progress", None) == None: 
       dict_input["in_progress"] = False 

     if errors: 
      raise ValidationError(errors) 

     return dict_input 

あります(現場レベルではない)。さて、問題は、特定のフィールドのみが関与するhttpメソッドのPATCHの場合、リクエスト本文に含まれていないフィールドに対してキーエラーが発生することです。

POSTメソッド、PUTメソッド、PATCHメソッドの両方で動作するように、上記のvalidate()メソッドを作成する最も良い方法は何ですか?

ありがとうございます。

+0

存在キーの数が異なるしている辞書を扱う、私はいつも 'に.get()'の呼び出しを使用しています。そのコードの使用とコードへのダイレクト・キー・アクセスが混在しています。どのキーがエラーをスローしているのかを明確に知らなければ、すべての辞書キーアクセスを '.get()'を使用するように変更して、それがNoneであれば適切に処理するために条件付きでラップします。 – Neelik

+1

@Neelik、問題は辞書にアクセスするwrtではありません。間違いなくget()を使うことができます。しかし、私の質問はwrtです。 patch()、create()およびput()メソッドの検証をどのように処理するかについて説明します。 create()とput()ではすべてのキーが使用できますが、patch()では一部のキーが見つからないことがあります。私はそれのための素朴な解決策を書くことができます。しかし、私はこれを行うための標準的な方法を知りたい。 –

答えて

1

フィールドを検証するためにvalidate_ < field_name>メソッドを定義できます。この方法では、フィールドが要求データに含まれている場合は検証されます。それ以外の場合は検証されません。例えば

def validate_year_start(self, value): 
    year_start = value 
    request  = self._context["request"] 
    user_dob = request.user.dob 
    age   = request.user.age 

    current_time = datetime.datetime.now() 
    if not user_dob: 
     user_dob = relativedelta(current_time, years=age) 

    if year_start < user_dob.year: 
     raise serializers.ValidationError({"year_start":"Year-start can't be before user's DOB"}) 
    return value 
+0

2つのフィールドを考慮する必要がある場合は、検証を行う必要があります。その場合、提案されたソリューションは機能しません。 –