URLs
For URI/URL validation the following types are available:
AnyUrl: any scheme allowed, top-level domain (TLD) not required, host required.AnyHttpUrl: schemehttporhttps, TLD not required, host required.HttpUrl: schemehttporhttps, TLD required, host required, max length 2083.FileUrl: schemefile, host not required.PostgresDsn: user info required, TLD not required, host required.PostgresDsnsupports multiple hosts. The following schemes are supported:postgrespostgresqlpostgresql+asyncpgpostgresql+pg8000postgresql+psycopgpostgresql+psycopg2postgresql+psycopg2cffipostgresql+py-postgresqlpostgresql+pygresql
MySQLDsn: schememysql, user info required, TLD not required, host required. Also, its supported DBAPI dialects:mysqlmysql+mysqlconnectormysql+aiomysqlmysql+asyncmymysql+mysqldbmysql+pymysqlmysql+cymysqlmysql+pyodbc
MariaDBDsn: schememariadb, user info required, TLD not required, host required. Also, its supported DBAPI dialects:mariadbmariadb+mariadbconnectormariadb+pymysql
CockroachDsn: schemecockroachdb, user info required, TLD not required, host required. Also, its supported DBAPI dialects:cockroachdb+asyncpgcockroachdb+psycopg2
AmqpDsn: schemaamqporamqps, user info not required, TLD not required, host not required.RedisDsn: schemeredisorrediss, user info not required, TLD not required, host not required (e.g.,rediss://:pass@localhost).MongoDsn: schememongodb, user info not required, database name not required, port not required, user info may be passed without user part (e.g.,mongodb://mongodb0.example.com:27017).
The above types (which all inherit from AnyUrl) will attempt to give descriptive
errors when invalid URLs are provided:
from pydantic import BaseModel, HttpUrl, ValidationError
class MyModel(BaseModel):
url: HttpUrl
m = MyModel(url='http://www.example.com')
print(m.url)
#> http://www.example.com/
try:
MyModel(url='ftp://invalid.url')
except ValidationError as e:
print(e)
"""
1 validation error for MyModel
url
URL scheme should be 'http' or 'https' [type=url_scheme, input_value='ftp://invalid.url', input_type=str]
"""
try:
MyModel(url='not a url')
except ValidationError as e:
print(e)
"""
1 validation error for MyModel
url
Input should be a valid URL, relative URL without a base [type=url_parsing, input_value='not a url', input_type=str]
"""
If you require a custom URI/URL type, it can be created in a similar way to the types defined above.
URL Properties¶
Assuming an input URL of http://samuel:[email protected]:8000/the/path/?query=here#fragment=is;this=bit,
the above types export the following properties:
scheme: the URL scheme (http), always set.host: the URL host (example.com), always set.username: optional username if included (samuel).password: optional password if included (pass).port: optional port (8000).path: optional path (/the/path/).query: optional URL query (for example,GETarguments or "search string", such asquery=here).fragment: optional fragment (fragment=is;this=bit).
If further validation is required, these properties can be used by validators to enforce specific behaviour:
from pydantic import (
BaseModel,
HttpUrl,
PostgresDsn,
ValidationError,
field_validator,
)
class MyModel(BaseModel):
url: HttpUrl
m = MyModel(url='http://www.example.com')
# the repr() method for a url will display all properties of the url
print(repr(m.url))
#> Url('http://www.example.com/')
print(m.url.scheme)
#> http
print(m.url.host)
#> www.example.com
print(m.url.port)
#> 80
class MyDatabaseModel(BaseModel):
db: PostgresDsn
@field_validator('db')
def check_db_name(cls, v):
assert v.path and len(v.path) > 1, 'database must be provided'
return v
m = MyDatabaseModel(db='postgres://user:pass@localhost:5432/foobar')
print(m.db)
#> postgres://user:pass@localhost:5432/foobar
try:
MyDatabaseModel(db='postgres://user:pass@localhost:5432')
except ValidationError as e:
print(e)
"""
1 validation error for MyDatabaseModel
db
Assertion failed, database must be provided
assert (None)
+ where None = MultiHostUrl('postgres://user:pass@localhost:5432').path [type=assertion_error, input_value='postgres://user:pass@localhost:5432', input_type=str]
"""
International domains¶
"International domains" (e.g. a URL where the host or TLD includes non-ascii characters) will be encoded via punycode (see this article for a good description of why this is important):
from pydantic import BaseModel, HttpUrl
class MyModel(BaseModel):
url: HttpUrl
m1 = MyModel(url='http://puny£code.com')
print(m1.url)
#> http://xn--punycode-eja.com/
m2 = MyModel(url='https://www.аррӏе.com/')
print(m2.url)
#> https://www.xn--80ak6aa92e.com/
m3 = MyModel(url='https://www.example.珠宝/')
print(m3.url)
#> https://www.example.xn--pbt977c/
Underscores in Hostnames
In Pydantic, underscores are allowed in all parts of a domain except the TLD. Technically this might be wrong - in theory the hostname cannot have underscores, but subdomains can.
To explain this; consider the following two cases:
exam_ple.co.uk: the hostname isexam_ple, which should not be allowed since it contains an underscore.foo_bar.example.comthe hostname isexample, which should be allowed since the underscore is in the subdomain.
Without having an exhaustive list of TLDs, it would be impossible to differentiate between these two. Therefore underscores are allowed, but you can always do further validation in a validator if desired.
Also, Chrome, Firefox, and Safari all currently accept http://exam_ple.com as a URL, so we're in good
(or at least big) company.
IP Addresses¶
Pydantic provides types for IP addresses and networks, which support the standard library IP address, interface, and network types.
IPvAnyAddress: allows either anIPv4Addressor anIPv6Address.IPvAnyInterface: allows either anIPv4Interfaceor anIPv6Interface.IPvAnyNetwork: allows either anIPv4Networkor anIPv6Network.
from pydantic import BaseModel
from pydantic.networks import IPvAnyAddress
class IpModel(BaseModel):
ip: IPvAnyAddress
print(IpModel(ip='127.0.0.1'))
#> ip=IPv4Address('127.0.0.1')
try:
IpModel(ip='http://www.example.com')
except ValueError as e:
print(e)
"""
1 validation error for IpModel
ip
value is not a valid IPv4 or IPv6 address [type=ip_any_address, input_value='http://www.example.com', input_type=str]
"""