Bonjour, êtes-vous Kakyo. Cette fois, j'aimerais écrire un article sur pydantic.
Pydantic est une bibliothèque qui utilise des annotations de type Python pour fournir des indications de type lors de l'exécution et pour fournir facilement des paramètres d'erreur lors de la validation des données.
Cette bibliothèque est utile pour définir un modèle de base de données dans SQLAlchemy.
Tout d'abord, lorsque vous le définissez, définissez-le comme suit.
from datetime import datetime
from typing import List
from pydantic import BaseModel
class Summer(BaseModel):
id: int
name: str # (variable):(Moule)として、Mouleを宣言する
friends: List[int] = [] # "="Vous pouvez également utiliser pour définir une valeur par défaut
created_at: datetime
external_data={
'id': '1',
'name' :'Bête senior',
'created_at': '2019-11-03 03:34',
'friends': [114,'514']
}
summer = Summer(**external_data)
print(summer.id)
#> 1 #Même si la valeur saisie est de type chaîne, elle sera automatiquement convertie en type Int.
print(repr(summer.created_at))
#> datetime.datetime(2019, 11, 3, 3, 34)
print(user.friends)
#> [114,514]
print(user.dict())
"""
{
'id': 1,
'name': 'Bête senior',
'created_at': datetime.datetime(2019, 11, 3, 3, 34),
'friends': [114, 514]
}
"""
Ainsi, lorsqu'une erreur de validation se produit, cela ressemble à ceci:
try:
User(created_at="Peint en noir",friends=[1,'2','voiture de luxe'])
except ValidationError as e:
print(e.json())
"""
[
{
"loc": [
"id"
],
"msg": "field required",
"type": "value_error.missing"
},
{
"loc": [
"name"
],
"msg": "field required",
"type": "value_error.missing"
},
{
"loc": [
"created_at"
],
"msg": "invalid datetime format",
"type": "type_error.datetime"
},
{
"loc": [
"friends",
2
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
"""
Ici, les objets renvoyés lorsqu'une erreur se produit sont les suivants.
Maintenant, en utilisant SQLAlchemy, l'ORM Wrapper de Python, nous allons faire ce qui suit: Vous pouvez concevoir un modèle SQL.
Le code ci-dessous cite à partir d'ici.
from typing import List
from sqlalchemy import Column, Integer, String
from sqlalchemy.dialects.postgresql import ARRAY
from sqlalchemy.ext.declarative import declarative_base
from pydantic import BaseModel, constr
Base = declarative_base()
class CompanyOrm(Base):
__tablename__ = 'companies'
id = Column(Integer, primary_key=True, nullable=False)
public_key = Column(String(20), index=True, nullable=False, unique=True)
name = Column(String(63), unique=True)
domains = Column(ARRAY(String(255)))
class CompanyModel(BaseModel):
id: int
public_key: constr(max_length=20)
name: constr(max_length=63)
domains: List[constr(max_length=255)]
class Config:
orm_mode = True
co_orm = CompanyOrm(
id=123,
public_key='foobar',
name='Testing',
domains=['example.com', 'foobar.com']
)
print(co_orm)
#> <orm_mode.CompanyOrm object at 0x7f0de1bc1cd0>
co_model = CompanyModel.from_orm(co_orm)
print(co_model)
#> id=123 public_key='foobar' name='Testing' domains=['example.com',
#> 'foobar.com']
Validators
Vous pouvez utiliser le ** Validator Decorator ** pour voir si les valeurs que vous entrez sont correctes et les relations complexes entre les objets.
from pydantic import BaseModel, ValidationError, validator
class UserModel(BaseModel):
name: str
username: str
password1: str
password2: str
@validator('name')
def name_must_contain_space(cls, v):
if ' ' not in v:
raise ValueError('must contain a space')
return v.title()
@validator('password2')
def passwords_match(cls, v, values, **kwargs):
if 'password1' in values and v != values['password1']:
raise ValueError('passwords do not match')
return v
@validator('username')
def username_alphanumeric(cls, v):
assert v.isalpha(), 'must be alphanumeric'
return v
print(UserModel(name='samuel colvin', username='scolvin', password1='zxcvbn',
password2='zxcvbn'))
#> name='Samuel Colvin' username='scolvin' password1='zxcvbn' password2='zxcvbn'
try:
UserModel(name='samuel', username='scolvin', password1='zxcvbn',
password2='zxcvbn2')
except ValidationError as e:
print(e)
"""
2 validation errors for UserModel
name
must contain a space (type=value_error)
password2
passwords do not match (type=value_error)
"""
Pre and per-item validators
Pour définir l'ordre de priorité lors du démarrage de Validator, utilisez les arguments suivants pre
, pre_item
.
pre
démarre le validateur avant tout autre validateur que vous avez défini.
Si ʻeach_item = True`, la validation sera exécutée pour chaque élément tel que la liste et le dictionnaire.
from typing import List
from pydantic import BaseModel, ValidationError, validator
class DemoModel(BaseModel):
square_numbers: List[int] = []
cube_numbers: List[int] = []
# '*' is the same as 'cube_numbers', 'square_numbers' here:
@validator('*', pre=True)
def split_str(cls, v):
if isinstance(v, str):
return v.split('|')
return v
@validator('cube_numbers', 'square_numbers')
def check_sum(cls, v):
if sum(v) > 42:
raise ValueError(f'sum of numbers greater than 42')
return v
@validator('square_numbers', each_item=True)
def check_squares(cls, v):
assert v ** 0.5 % 1 == 0, f'{v} is not a square number'
return v
@validator('cube_numbers', each_item=True)
def check_cubes(cls, v):
# 64 ** (1 / 3) == 3.9999999999999996 (!)
# this is not a good way of checking cubes
assert v ** (1 / 3) % 1 == 0, f'{v} is not a cubed number'
return v
print(DemoModel(square_numbers=[1, 4, 9]))
#> square_numbers=[1, 4, 9] cube_numbers=[]
print(DemoModel(square_numbers='1|4|16'))
#> square_numbers=[1, 4, 16] cube_numbers=[]
print(DemoModel(square_numbers=[16], cube_numbers=[8, 27]))
#> square_numbers=[16] cube_numbers=[8, 27]
try:
DemoModel(square_numbers=[1, 4, 2])
except ValidationError as e:
print(e)
"""
1 validation error for DemoModel
square_numbers -> 2
2 is not a square number (type=assertion_error)
"""
try:
DemoModel(cube_numbers=[27, 27])
except ValidationError as e:
print(e)
"""
1 validation error for DemoModel
cube_numbers
sum of numbers greater than 42 (type=value_error)
"""
Validate Always Pour des raisons de performances, par défaut, ce validateur ne démarrera pas si aucune valeur n'est donnée. Cependant, l'argument doit être défini sur ʻalways = True` pour être exécuté même si aucune valeur n'est donnée.
from datetime import datetime
from pydantic import BaseModel, validator
class DemoModel(BaseModel):
ts: datetime = None
@validator('ts', pre=True, always=True)
def set_ts_now(cls, v):
return v or datetime.now()
print(DemoModel())
#> ts=datetime.datetime(2019, 10, 24, 15, 7, 51, 449261)
print(DemoModel(ts='2017-11-08T14:00'))
#> ts=datetime.datetime(2017, 11, 8, 14, 0)
Ce qui précède est l'utilisation de base de Pydantic. Vous pouvez l'utiliser pour définir des validations et des types dans Python pour les steamers SQL. Pour les paramètres détaillés, reportez-vous au document officiel ci-dessous.
Documentation officielle de Pydanit (https://pydantic-docs.helpmanual.io/)
Recommended Posts