[PYTHON] Erste Schritte mit Pydantic

Hallo, bist du Kakyo? Dieses Mal möchte ich einen Artikel über pydantic schreiben.

Was ist Pydantic?

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.

Modell-

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.

Versuchen Sie, mit SQLAlchemy zu kombinieren

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)

Schließlich

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.

Verweise

Offizielle Pydanit-Dokumentation (https://pydantic-docs.helpmanual.io/)

Recommended Posts

Erste Schritte mit Pydantic
Erste Schritte mit Android!
1.1 Erste Schritte mit Python
Erste Schritte mit apache2
Erste Schritte mit Python
Erste Schritte mit Django 1
Einführung in die Optimierung
Erste Schritte mit Numpy
Erste Schritte mit Spark
Erste Schritte mit Python
Erste Schritte mit Jython
Erste Schritte mit Django 2
Übersetzen Erste Schritte mit TensorFlow
Einführung in Python-Funktionen
Einführung in Tkinter 2: Button
Erste Schritte mit Go Assembly
Erste Schritte mit PKI mit Golang ―― 4
Erste Schritte mit Python Django (1)
Erste Schritte mit Python Django (4)
Erste Schritte mit Python Django (3)
Einführung in Python Django (6)
Erste Schritte mit Python Django (5)
Einführung in Git (1) History-Speicher
Erste Schritte mit Sphinx. Generieren Sie Docstring mit Sphinx
Erste Schritte mit Python für PHPer-Klassen
Erste Schritte mit Julia für Pythonista
Erste Schritte mit Python Grundlagen von Python
Erste Schritte mit der Cisco Spark REST-API
Beginnend mit USD unter Windows
Erste Schritte mit genetischen Python-Algorithmen
Erste Schritte mit Python 3.8 unter Windows
Erste Schritte mit Python für PHPer-Funktionen
Erste Schritte mit der CPU-Diebstahlzeit
Grale fangen an
Erste Schritte mit Python Web Scraping Practice
Erste Schritte mit Python für PHPer-Super Basics
Erste Schritte mit Python Web Scraping Practice
Erste Schritte mit Dynamo von Python Boto
Erste Schritte mit Lisp für Pythonista: Ergänzung
Erste Schritte mit Heroku, Bereitstellen der Flaschen-App
Erste Schritte mit TDD mit Cyber-dojo bei MobPro
Erste Schritte mit Python mit 100 Klopfen bei der Sprachverarbeitung
Django 1.11 wurde mit Python3.6 gestartet
MongoDB-Grundlagen: Erste Schritte mit CRUD mit JAVA
Erste Schritte mit dem Zeichnen mit matplotlib: Schreiben einfacher Funktionen
Erste Schritte mit der japanischen Übersetzung des Keras Sequential-Modells
[Übersetzung] Erste Schritte mit Rust für Python-Programmierer
Django Erste Schritte Teil 2 mit dem Eclipse Plugin (PyDev)
Beginnen Sie mit MicroPython
Erste Schritte mit AWS IoT in Python
Erste Schritte mit Pythons Ast-Modul (Verwenden von NodeVisitor)
Materialien zum Lesen, wenn Sie mit Python beginnen
Einstellungen für den Einstieg in MongoDB mit Python
Erste Schritte mit Pandas: Grundkenntnisse, an die Sie sich zuerst erinnern sollten
Erste Schritte mit Google App Engine für Python und PHP