如何在Pydantic中限制URL验证仅针对特定主机或网站
在Pydantic中限制URL仅允许特定主机的最佳方案
针对你的需求,有两种实用方案可以实现URL主机的限制,以下是具体实现:
方案一:字段验证器(适合单个模型场景)
直接给url字段添加自定义验证逻辑,简单直接,适合仅在单个模型中使用的场景:
from pydantic import BaseModel, AnyUrl, field_validator from pydantic_core import ValidationError # 定义允许的主机列表 ALLOWED_HOSTS = {"x.com", "y.com"} class Media(BaseModel): url: AnyUrl @field_validator("url") def validate_host(cls, v: AnyUrl) -> AnyUrl: # 利用AnyUrl已解析的host属性进行校验 if v.host not in ALLOWED_HOSTS: raise ValueError(f"URL主机必须是{', '.join(ALLOWED_HOSTS)}中的一个") return v # 验证测试 if __name__ == "__main__": # 合法URL测试 try: valid_media = Media(url="https://x.com/photo.png") print("验证通过:", valid_media) except ValidationError as e: print("验证失败:", e) # 非法URL测试 try: invalid_media = Media(url="https://z.com/file.mp4") print("验证通过:", invalid_media) except ValidationError as e: print("验证失败:", e)
方案二:自定义受限URL类型(适合多模型复用场景)
如果多个模型都需要相同的主机限制,自定义一个继承自AnyUrl的类型可以实现逻辑复用:
from pydantic import BaseModel, AnyUrl, GetCoreSchemaHandler from pydantic_core import core_schema from typing import Any from pydantic_core import ValidationError ALLOWED_HOSTS = {"x.com", "y.com"} class RestrictedUrl(AnyUrl): @classmethod def __get_pydantic_core_schema__(cls, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: # 继承AnyUrl的原有验证逻辑 base_schema = handler(source_type) # 追加主机校验逻辑 validated_schema = core_schema.no_info_after_validator_function( cls.validate_host, base_schema, ) return validated_schema @classmethod def validate_host(cls, v: AnyUrl) -> AnyUrl: if v.host not in ALLOWED_HOSTS: raise ValueError(f"URL主机必须是{', '.join(ALLOWED_HOSTS)}中的一个") return v class Media(BaseModel): url: RestrictedUrl # 验证测试 if __name__ == "__main__": try: valid_media = Media(url="https://y.com/video.mp4") print("验证通过:", valid_media) except ValidationError as e: print("验证失败:", e)
兼容Pydantic v1的写法
如果你仍在使用Pydantic v1,只需将@field_validator替换为@validator即可:
from pydantic import BaseModel, AnyUrl, validator from pydantic.error_wrappers import ValidationError ALLOWED_HOSTS = {"x.com", "y.com"} class Media(BaseModel): url: AnyUrl @validator("url") def validate_host(cls, v): if v.host not in ALLOWED_HOSTS: raise ValueError(f"URL主机必须是{', '.join(ALLOWED_HOSTS)}中的一个") return v
内容的提问来源于stack exchange,提问作者pyGenius
相关产品推荐
相关产品推荐

