Hallo, bist du Kakyo? Dieses Mal möchte ich einen Artikel über pydantic schreiben.
Pydantic ist eine Bibliothek, die Python-Typanmerkungen verwendet, um zur Laufzeit Typhinweise bereitzustellen und während der Datenüberprüfung auf einfache Weise Fehlereinstellungen bereitzustellen.
Diese Bibliothek ist nützlich, um ein Datenbankmodell in SQLAlchemy zu definieren.
Wenn Sie es definieren, definieren Sie es zunächst wie folgt.
from datetime import datetime
from typing import List
from pydantic import BaseModel
class Summer(BaseModel):
id: int
name: str # (Variable):(Schimmel)として、Schimmelを宣言する
friends: List[int] = [] # "="Sie können auch einen Standardwert definieren
created_at: datetime
external_data={
'id': '1',
'name' :'Beast Senior',
'created_at': '2019-11-03 03:34',
'friends': [114,'514']
}
summer = Summer(**external_data)
print(summer.id)
#> 1 #Selbst wenn der eingegebene Wert ein Zeichenfolgentyp ist, wird er automatisch in einen Int-Typ konvertiert.
print(repr(summer.created_at))
#> datetime.datetime(2019, 11, 3, 3, 34)
print(user.friends)
#> [114,514]
print(user.dict())
"""
{
'id': 1,
'name': 'Beast Senior',
'created_at': datetime.datetime(2019, 11, 3, 3, 34),
'friends': [114, 514]
}
"""
Wenn also ein Validierungsfehler auftritt, sieht er folgendermaßen aus:
try:
User(created_at="Schwarz lackiert",friends=[1,'2','Luxusauto'])
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"
}
]
"""
Hier sind die Objekte, die zurückgegeben werden, wenn ein Fehler auftritt, wie folgt.
Mit SQLAlchemy, Pythons ORM Wrapper, gehen wir nun wie folgt vor: Sie können ein SQL-Modell entwerfen.
Der folgende Code zitiert von hier.
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
Mit dem ** Validator Decorator ** können Sie überprüfen, ob die von Ihnen eingegebenen Werte korrekt sind und welche komplexen Beziehungen zwischen den Objekten bestehen.
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
Verwenden Sie die folgenden Argumente "pre", "pre_item", um die Prioritätsreihenfolge beim Starten von Validator festzulegen.
pre
startet den Validator vor jedem anderen von Ihnen festgelegten Validator.
Wenn Sie "each_item = True" setzen, wird die Validierung für jedes Element wie Liste und Wörterbuch ausgeführt.
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 Aus Leistungsgründen wird dieser Validator standardmäßig nicht gestartet, wenn kein Wert angegeben wird. Das Argument muss jedoch auf "always = True" gesetzt werden, damit es ausgeführt werden kann, auch wenn kein Wert angegeben wird.
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)
Das Obige ist die grundlegende Verwendung von Pydantic. Sie können dies verwenden, um Validierungen und Typen in Python für SQL-Dampfer festzulegen. Detaillierte Einstellungen finden Sie im folgenden offiziellen Dokument.
Offizielle Pydanit-Dokumentation (https://pydantic-docs.helpmanual.io/)
Recommended Posts