A principal maneira do Pydantic de definir esquemas de dados é por meio de modelos. Um modelo Pydantic é um objeto, semelhante a um modelo Python classe de dadosque define e armazena dados sobre uma entidade com anotada campos. Ao contrário das classes de dados, o foco do Pydantic está centrado na análise, validação e serialização automáticas de dados.
A melhor maneira de entender isso é criar seus próprios modelos, e é isso que o senhor fará a seguir.
Trabalhando com Pydantic BaseModels
Suponha que o senhor esteja criando um aplicativo usado por um departamento de recursos humanos para gerenciar as informações dos funcionários e precise de uma maneira de verificar se as informações dos novos funcionários estão no formato correto. Por exemplo, cada funcionário deve ter um ID, nome, e-mail, data de nascimento, salário, departamento e seleção de benefícios. Esse é um caso de uso perfeito para um modelo Pydantic!
Para definir seu modelo de funcionário, o senhor cria um classe que herda do Pydantic’s BaseModel
:
Primeiro, o senhor importa as dependências necessárias para definir seu modelo de funcionário. Em seguida, o senhor cria um enum para representar os diferentes departamentos da sua empresa, e o senhor usará isso para anotar o department
em seu modelo de funcionário.
Em seguida, o senhor define seu modelo Pydantic, Employee
, que herda de BaseModel
e define os nomes e os tipos esperados dos campos de seus funcionários por meio de anotações. Aqui está um detalhamento de cada campo que o senhor definiu em Employee
e como o Pydantic o valida quando um Employee
é instanciado:
employee_id
: Este é o UUID do funcionário para o qual o senhor deseja armazenar informações. Ao usar oUUID
a Pydantic garante que esse campo seja sempre um UUID válido. Cada instância deEmployee
receberá um UUID por padrão, conforme especificado pelo senhor ao chamaruuid4()
.name
: O nome do funcionário, que o Pydantic espera que seja uma cadeia de caracteres.email
: A Pydantic garantirá que cada funcionárioemail
é válido usando a funçãoemail-validator
do Python.date_of_birth
: A data de nascimento de cada funcionário deve ser uma data válida, conforme anotado pelodate
do Python’sdatetime
do Python. Se o senhor passar uma string paradate_of_birth
, o Pydantic tentará analisá-la e convertê-la em umdate
objeto.salary
: Este é o salário do funcionário e espera-se que seja um float.department
: O departamento de cada funcionário deve ser um dos seguintesHR
,SALES
,IT
, ouENGINEERING
, conforme definido em seuDepartment
enum.elected_benefits
: Esse campo armazena se o funcionário escolheu benefícios, e a Pydantic espera que ele seja um booleano.
A maneira mais simples de criar um Employee
é instanciá-lo como o senhor faria com qualquer outro objeto Python. Para fazer isso, abra um objeto Python REPL e execute o seguinte código:
Nesse bloco, o senhor importa Employee
e cria um objeto com todos os campos de funcionário necessários. O Pydantic valida e coage com êxito os campos que o senhor passou e cria um objeto Employee
válido. Observe como o Pydantic converte automaticamente sua string de data em um objeto date
e seu objeto IT
para seus respectivos Department
enum.
Em seguida, veja como o Pydantic responde quando o usuário tenta passar dados inválidos para um Employee
instância:
Neste exemplo, o senhor criou uma instância de Employee
com campos de dados inválidos. O Pydantic fornece uma mensagem de erro detalhada para cada campo, informando o que era esperado, o que foi recebido e onde o senhor pode ir para saber mais sobre o erro.
Essa validação detalhada é poderosa porque impede que o senhor armazene dados inválidos no Employee
. Isso também dá ao senhor a certeza de que o Employee
que os objetos instanciados sem erros contêm os dados que o senhor espera e que pode confiar nesses dados no seu código ou em outros aplicativos.
O site da Pydantic BaseModel
está equipado com um conjunto de métodos que facilitam a criação de modelos a partir de outros objetos, como dicionários e JSON. Por exemplo, se o senhor quiser instanciar um Employee
a partir de um dicionário, o senhor pode usar o comando .model_validate()
método de classe:
Aqui, o senhor cria new_employee_dict
um dicionário com os campos do funcionário e o passa para .model_validate()
para criar um Employee
instância. Nos bastidores, o Pydantic valida cada entrada do dicionário para garantir que esteja em conformidade com os dados que o senhor espera. Se algum dos dados for inválido, o Pydantic lançará um erro da mesma forma que o senhor viu anteriormente. O senhor também será notificado se algum campo estiver faltando no dicionário.
O senhor pode fazer a mesma coisa com objetos JSON usando .model_validate_json()
:
Neste exemplo, new_employee_json
é uma cadeia de caracteres JSON válida que armazena os campos do funcionário, e o senhor usa .model_validate_json()
para validar e criar um Employee
a partir de new_employee_json
. Embora possa parecer sutil, a capacidade de criar e validar modelos Pydantic a partir do JSON é poderosa porque o JSON é uma das formas mais populares de transferir dados pela Web. Esse é um dos motivos pelos quais o FastAPI se baseia no Pydantic para criar APIs REST.
O senhor também pode serializar modelos Pydantic como dicionários e JSON:
Aqui, o senhor usa .model_dump()
e .model_dump_json()
para converter seu new_employee
em um dicionário e em uma string JSON, respectivamente. Observe como o .model_dump_json()
retorna um objeto JSON com date_of_birth
e department
armazenados como cadeias de caracteres.
Embora o Pydantic já tenha validado esses campos e convertido seu modelo em JSON, quem usar esse JSON downstream não saberá que date_of_birth
precisa ser um date
e department
precisa ser uma categoria em seu Department
enum. Para resolver isso, o senhor pode criar um esquema JSON do seu Employee
modelo.
Os esquemas JSON informam ao senhor quais campos são esperados e quais valores são representados em um objeto JSON. O senhor pode pensar nisso como a versão JSON do seu Employee
definição de classe. Veja como o senhor gera um esquema JSON para Employee
:
Quando o senhor ligar .model_json_schema()
o senhor obtém um dicionário que representa o esquema JSON do seu modelo. A primeira entrada que o senhor vê mostra os valores que department
podem assumir. O senhor também vê informações sobre como os campos devem ser formatados. Por exemplo, de acordo com este esquema JSON, employee_id
deve ser um UUID e date_of_birth
deve ser uma data.
O senhor pode converter seu esquema JSON em uma string JSON usando json.dumps()
, o que permite que o senhor converta praticamente qualquer linguagem de programação para validar objetos JSON produzidos pelo seu Employee
do seu modelo. Em outras palavras, o Pydantic não só pode validar os dados recebidos e serializá-los como JSON, mas também fornece a outras linguagens de programação as informações necessárias para validar os dados do seu modelo por meio de esquemas JSON.
Com isso, o senhor agora entende como usar o BaseModel
para validar e serializar seus dados. A seguir, o senhor aprenderá a usar campos para personalizar ainda mais a validação.
Uso de campos para personalização e metadados
Até agora, seu Employee
valida o tipo de dados de cada campo e garante que alguns dos campos, como email
, date_of_birth
, e department
, assumem formatos válidos. No entanto, digamos que o senhor também queira garantir que salary
seja um número positivo, name
não é uma string vazia, e email
contenha o nome de domínio de sua empresa. O senhor pode usar a função Field
da Pydantic para fazer isso.
O Field
permite que o senhor personalize e adicione metadados aos campos do seu modelo. Para ver como isso funciona, dê uma olhada neste exemplo:
Aqui, o senhor importa Field
juntamente com as outras dependências que usou anteriormente e atribui valores padrão a algumas das dependências do Employee
campos. Aqui está um detalhamento do Field
que o senhor usou para adicionar validação e metadados adicionais aos seus campos:
default_factory
: O senhor usa isso para definir um callable que gera valores padrão. No exemplo acima, o senhor definedefault_factory
parauuid4
. Esta chamadauuid4()
para gerar um UUID aleatório para oemployee_id
quando necessário. O senhor também pode usar um lambda para maior flexibilidade.frozen
: Esse é um parâmetro booleano que o senhor pode definir para tornar seus campos imutáveis. Isso significa que, quando ofrozen
é definido comoTrue
o campo correspondente não poderá ser alterado depois que o modelo for instanciado. Neste exemplo,employee_id
,name
, edate_of_birth
são tornados imutáveis usando ofrozen
.min_length
: O senhor pode controlar o comprimento dos campos de string commin_length
emax_length
. No exemplo acima, o senhor garante quename
tenha pelo menos um caractere de comprimento.pattern
: Para campos de string, o senhor pode definirpattern
para um regex para corresponder a qualquer padrão que o senhor esteja esperando para esse campo. Por exemplo, quando o senhor usa a expressão regex no exemplo acima paraemail
, o Pydantic garantirá que todos os e-mails terminem com@example.com
.alias
: O senhor pode usar esse parâmetro quando quiser atribuir um alias aos seus campos. Por exemplo, o senhor pode permitir quedate_of_birth
seja chamado debirth_date
ousalary
a ser chamadocompensation
. O senhor pode usar esses aliases ao instanciar ou serializar um modelo.gt
: Esse parâmetro, abreviação de “greater than” (maior que), é usado em campos numéricos para definir valores mínimos. Neste exemplo, a definição degt=0
garante que osalary
seja sempre um número positivo. O Pydantic também tem outros restrições numéricas, tais comolt
que é a abreviação de “less than” (menos que).repr
: Esse parâmetro booleano determina se um campo é exibido na representação de campo do modelo. Neste exemplo, o senhor não verádate_of_birth
ousalary
quando o senhor imprimir umEmployee
instância.
Para ver essa validação extra em ação, observe o que acontece quando o senhor tenta criar um Employee
com dados incorretos:
Aqui, o senhor importa o Employee
atualizado e tenta validar um dicionário com dados incorretos. Em resposta, o Pydantic apresenta três erros de validação dizendo que o name
precisa ter pelo menos um caractere, email
deve corresponder ao nome de domínio de sua empresa, e salary
deve ser maior que zero.
Agora observe os recursos adicionais que o senhor obtém ao validar corretamente Employee
dados:
Neste bloco, o senhor cria um dicionário e um Employee
com o .model_validate()
. Em employee_data
, observe como o senhor usou birth_date
em vez de date_of_birth
e compensation
em vez de salary
. O Pydantic reconhece esses aliases e atribui internamente seus valores ao nome de campo correto.
Como o senhor define repr=False
, o senhor pode ver que salary
e date_of_birth
não são exibidos no Employee
o senhor precisa acessá-los explicitamente como atributos para ver seus valores. O senhor precisa acessá-los explicitamente como atributos para ver seus valores. Por fim, observe o que acontece quando o senhor tenta alterar um campo congelado:
Aqui, o senhor primeiro altera o valor de department
de IT
para HR
. Isso é perfeitamente aceitável porque department
não é um campo congelado. No entanto, quando o senhor tenta alterar name
, o Pydantic apresenta um erro dizendo que name
é um campo congelado.
Agora o senhor tem uma sólida compreensão do conceito de Pydantic BaseModel
e do Field
classes. Somente com elas, o senhor pode definir muitas regras de validação e metadados diferentes em seus esquemas de dados, mas às vezes isso não é suficiente. A seguir, o senhor levará sua validação de campo ainda mais longe com os validadores Pydantic.