Mangu Singh Rajpurohit
Mangu Singh Rajpurohit

Reputation: 11420

Validation in patch method in django rest framework

Following is my model definition

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)

Following is my serializer

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

I have defined validate() method in serializer, which performs validations at serializer level(not at field level). Now, the problem is that, for PATCH http method, where only certain fields are involved, it gives keyerror for those fields, which are not part of request body.

What's the best way to write the above validate() method, so that it works in both POST, PUT and PATCH methods ?

Thanks in advance.

Upvotes: 11

Views: 5072

Answers (2)

Dineshs91
Dineshs91

Reputation: 2214

Use self.partial in the validate method to find out if it's a partial update.

def validate(self, data):
    if self.partial:
        print("Partial update")
    return data

Upvotes: 11

Emma
Emma

Reputation: 134

you can define validate_< field_name > method to validate specific field, in this way if the field is included in request data, it will be validated; otherwise it will not be validated.

For example:

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

Upvotes: 0

Related Questions