Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 500
Mangu Singh Rajpurohit Avatar asked Feb 13 '17 17:02

Mangu Singh Rajpurohit


People also ask

How do you validate data in DRF?

DRF enforces data validation in the deserialization process, which is why you need to call is_valid() before accessing the validated data. If the data is invalid, errors are then appended to the serializer's error property and a ValidationError is thrown. There are two types of custom data validators: Custom field.

How do I validate an email in Django REST framework?

This can be easily done by automatically sending the verification email with an activation link. Such a link contains the unique token assigned to the user. After opening the activation link in the web browser the request is sent to the web application (Django Rest Framework).


1 Answers

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
like image 117
Dineshs91 Avatar answered Sep 29 '22 07:09

Dineshs91