DEV Community

Tue
Tue

Posted on

Using Pydantic to validate inputs

I continued to contribute to partner-finder which is one of Hacktoberfest the repo.

The issue:

The repo owner posted a issue on validating phone number, email address, social links and official user fields in the api of the project whenever there is a POST request to the server.

Solving:

The repo owner suggested using pydantic or marshmallow to make validating those fields easier. I decided to installed pydantic as it has better documents and I felt just right using it.

Validating phone number:

I created a class FieldTestModel inheriting BaseModel with fields that needed validating. I then added a validator decorator to be parsed and validated in which I used regular expression to check the phone number.

class FieldTestModel(BaseModel):
        phoneNum: str
        assigned: str
        email: EmailStr
        socialLink: HttpUrl

        @validator("phoneNum")
        def check_phoneNumber_format(cls, v):
            regExs = (r"\(\w{3}\) \w{3}\-\w{4}", r"^\w{3}\-\w{4}$")
            if not re.search(regExs[0], v):
                return ValueError("not match")
            return v
Enter fullscreen mode Exit fullscreen mode

Validating email address, social links:

Luckily, pydantic has its own field types that self-validate so I used EmailStr and HttpUrl, if there was any error, it would throw.

Validating assigned (official user):

The data of assigned is an username, I needed to check if the username matches with one in the database. Firstly, I exported getl_all_users from a different module users.py to leads.py to use it. I simply checked if assigned presented in the array of users

        @validator("assigned")
        def check_assigned(cls, v):
            users_response = get_all_users()
            if not users_response:
                raise ValueError("get_all_users() doesnt work")
            if v not in users_response["users"]:
                raise ValueError(f"{v!r} is not a registered user")
            return v
Enter fullscreen mode Exit fullscreen mode

And the rest of the code

    try:
        phoneNum = str(body.get("phone")).strip()
        assigned = body.get("assigned")
        email = EmailStr(body.get("email"))
        link = body.get("twitter")

        testInstance = FieldTestModel(phoneNum=phoneNum, assigned=assigned, email=email, socialLink=link)

        testInstance.socialLink = link
        link = body.get("facebook")
        testInstance.socialLink = link
        link = body.get("instagram")
        testInstance.socialLink = link
    except ValidationError as err:
        return {"message": "{error}".format(error=err.errors()[0])}
Enter fullscreen mode Exit fullscreen mode

Testing

I could test using Postman but instead I used the project's own api doc which includes a testing tool. Very cool!
Image description
Image description
You can check out my PR

Discussion (0)