1+ from pydantic import BaseModel , ValidationError , Field , EmailStr , HttpUrl , SecretStr , field_validator , model_validator
2+ from datetime import datetime , UTC
3+ from functools import partial
4+ from uuid import UUID , uuid4
5+ from typing import Literal ,Annotated
6+
7+ class User (BaseModel ):
8+ uid : UUID = Field (default_factory = uuid4 )
9+ username : Annotated [str , Field (min_length = 3 , max_length = 20 )]
10+ email : EmailStr
11+ age : Annotated [int , Field (ge = 13 ,le = 130 )]
12+
13+ website : HttpUrl | None = None
14+ password : SecretStr
15+
16+ verified_at : datetime | None = None
17+
18+ bio : str = ""
19+ is_active : bool = True
20+
21+ full_name : str | None = None
22+
23+ @field_validator ("username" )
24+ @classmethod
25+ def validate_username (cls , v : str ) -> str :
26+ if not v .replace ("_" ,"" ).isalnum ():
27+ raise ValueError ("Username must be alphanumeric or contain underscores" )
28+ return v .lower ()
29+
30+ @field_validator ("website" , mode = "before" )
31+ @classmethod
32+ def add_https (cls , v : str | None ) -> str | None :
33+ if v and not v .startswith (("http://" ,"https://" )):
34+ return f"https://{ v } "
35+ return v
36+
37+ class BlogPost (BaseModel ):
38+ title : Annotated [str , Field (min_length = 1 ,max_length = 200 )]
39+ content : Annotated [str , Field (min_length = 20 )]
40+ view_count : int = 0
41+ is_published : bool = False
42+
43+ tags : list [str ] = Field (default_factory = list )
44+
45+ # create_at : datetime = Field(default_factory=lambda : datetime.now(tz=UTC))
46+ # both will do same work lambda or partial function
47+ create_at : datetime = Field (default_factory = partial (datetime .now ,tz = UTC ))
48+
49+ author_id : str | int
50+ status : Literal ["draft" , "published" , "archived" ] = "draft"
51+
52+ slug : Annotated [str , Field (pattern = r"^[a-z0-9-]+$" )]
53+
54+
55+ class UserRegistration (BaseModel ):
56+ email : EmailStr
57+ password : str
58+ confirm_password : str
59+
60+ @model_validator (mode = "after" )
61+ def passwords_match (self ) -> "UserRegistration" :
62+ if self .password != self .confirm_password :
63+ raise ValueError ("Passwords do not match" )
64+ return self
65+
66+ try :
67+ registration = UserRegistration (
68+ 69+ password = "mysecretpassword" ,
70+ confirm_password = "mysecretpassword1" ,
71+ )
72+ except ValidationError as e :
73+ print (e )
74+
0 commit comments