Python

How to Use Pydantic Enums for Improved Data Consistency

Pydantic Enums are special guides for our computer tasks. They act like traffic signals, permitting only specific, approved options for our data. It’s similar to sticking to a particular type of information when starting a new project. Using Pydantic Enums is like having a checklist. We decide what’s allowed, and Pydantic Enums ensure that everything matches the list. It’s like following a set of instructions to build a model. Similarly, Pydantic Enums help our computer to handle the information correctly, resulting in smoother operations without confusion. 

Method 1: Using Pydantic Enums for Improved Data Consistency

Pydantic Enums are like special tools in the Pydantic library that can help keep our data organized and accurate in Python programs. Imagine we have a list of choices and we want to make sure that people only pick from that list. Enums help us with that. Here’s how we can use the Pydantic Enums for improved data consistency:

Before we start with the Pydantic Enums, the prerequisites are to ensure that we have the Pydantic packages installed in our compiler. We will work on the online “Google Colab” Python compiler. To install the Pydantic on the Google Colab, we use the following command:

!pip install pydantic

After adding the Pydantic packages to the project, we want to import the tools from these packages. So, using the following commands bring these necessary tools from Python.

from enum import Enum
from pydantic import BaseModel

After importing the necessary modules/tools, let’s create the Pydantic’s Enums. To create the Enums, we have to define the “Enum” class which specifies the values for our field. We can imagine the Enums as having a few options to choose from. Enum helps us to list them nicely, the “Enum” class takes the two parameters as its parameter “str” and the “Enum” itself. Then, we define the possible values/options of our field for the Enum. This can be done following the mentioned code:

class StatusEnum(str, Enum):
    request= "pending"
    application= "approved"
    letter = "rejected"

After defining the Enum, we define a model that uses the Enum for the fields that require consistent values or assign the values to the fields of the Enum. It is like creating a form for some items from which one of the options should be picked. We use Pydantic to set up this form and create a model with the “list” name that is inherited from the Pydantic’s BaseModel. The required fields for this model is the name and the status:

class list(BaseModel):
    name: str
    status: StatusEnum

Once this is done, we create an instance for the data. Now, we can use the form/model to check what option we picked. Pydantic makes sure that the choice is one of the options that we listed:

data = {"name": "Example list", "status": "approved"}
list = list(**data)

If we try to pick something that is not on our list, Pydantic tells us that the option is not there. If we want to know what we picked earlier from the list, Pydantic helps us with that and we can see the choices that we listed by accessing the Enum values using the “Enum” class itself.

list_dump = list.model_dump()
print(item_dump)
StatusEnum.application

This is the code for the example that is previously mentioned with the output:

from enum import Enum
from pydantic import BaseModel
class StatusEnum(str, Enum):
    request = "pending"
    application = "approved"
    letter = "rejected"
class Item(BaseModel):
    name: str
    status: StatusEnum
data = {"name": "Example Item", "status": "approved"}
item = Item(**data)  
item_dump = item.model_dump()
print(item_dump)
StatusEnum.application

From the output, it is visible that using Pydantic Enums is like having a competent help. It makes sure that only the right choices are involved. This is helpful because it keeps our data nice and tidy, and it stops the mistakes from happening. Plus, it makes our code easy to read using good names for the choices. Also, Pydantic Enums work best when we have a clear list of choices. Enums raises the validation error and might not be the best fit if the choices can change or come from somewhere else.

Method 2: Using Pydantic Enum for the Real-World Applications

Suppose we are building a task management app to keep track of our daily tasks. To ensure an accurate and consistent data, we decide to implement the Pydantic Enums. For instance, let’s assume our tasks can have one of three statuses “To-Do”, “In Progress”, and “Done”. To make sure that no incorrect statuses come in, we can use the Pydantic Enums. So, after installing the important Pydantic packages, we create the “WorkStatus Enum”. We begin by designing an “Enum” class that enlists the allowed task statuses. The enlist task statuses in this “Enum” class are the to-do tasks, in-progress tasks, and the tasks that are already done.

from enum import Enum
from pydantic import BaseModel
class WorkStatusEnum(str, Enum):
    TODO = "todo"
    IN_PROGRESS = "in_progress"
    DONE = "done"

After we define the Enum workstatus, we build the workmodel to construct a Pydantic model, incorporating the WorkstatusEnum for the tasks’ status. The fields for this model are the “task_priority” and the “status” of the tasks. The data type for the task priority is “str” and we pass the “Enum” class as workstatus that we created earlier to the “status” field.

class workModel(BaseModel):
    task_priority: str
    status: WorkStatusEnum

To enforce the valid status, the workModel now acts as a filter or a gate to ensure that only legitimate statuses are used. Here, we create the instance for the “task_data” workmodel where we define the corresponding values for the enlisted fields in the Enum workstatus. We specify the task_priority for the task to be “wash dishes” and its status is “in progress”. Then, we create the object for this instance.

At this point, we can also validate the status if we provide some other value of status than it is described in the Enum workstatus required fields. Then, Pydantic raises the validation error here.

task_data = {"task_priority": "Wash dishes", "status": "in_progress"}
task = workModel(**task_data)  
#invalid_task_data = {"task_priority": "Invalid Task", "status": "invalid_status"}
#invalid_task = TaskModel(**invalid_task_data)  # Raises validation error

Pydantic’s model also handles the transformation between the Enum values and their string forms during serialization (converting a complex data to strings) and deserialization. This can be done as follows:

task_dump = task.model_dump()
print(task_dump)

We can easily access the Enum values through the “Enum” class itself in the following way:

WorkStatusEnum.TODO

By applying the Pydantic Enums in this scenario, we ensure that only the accurate task statuses are used, diminishing the possibility of mistakes. This approach also improves the clarity of our code by explicitly showing the permissible options for task statuses.

Here’s the code for the example:

from enum import Enum
from pydantic import BaseModel
class WorkStatusEnum(str, Enum):
    TODO = "todo"
    IN_PROGRESS = "in_progress"
    DONE = "done"
class workModel(BaseModel):
    task_priority: str
    status: WorkStatusEnum
task_data = {"task_priority": "Wash dishes", "status": "in_progress"}
task = workModel(**task_data)  
#invalid_task_data = {"task_priority": "Invalid Task", "status": "invalid_status"}
#invalid_task = TaskModel(**invalid_task_data)  # Raises validation error
task_dump = task.model_dump()
print(task_dump)
WorkStatusEnum.TODO

Conclusion

Pydantic Enums are like trusted tools for keeping the data in check within Python programs. They help ensure that we only use the right choices, avoiding mix-ups and keeping our code easy to read. We have done two examples of the Pydantic Enums in this article. Each example explains how we can implement the Pydantic Enums for the real-world applications to improve the data consistency. Whether handling task statuses, user roles, or other options, Pydantic Enums ensures that our programs work smoothly and don’t get tangled up.

About the author

Omar Farooq

Hello Readers, I am Omar and I have been writing technical articles from last decade. You can check out my writing pieces.