सीरियलाइजेशन
मॉडल विशेषताओं को सीधे उनके फ़ील्ड नामों (उदाहरण के लिए model.foobar
) के माध्यम से एक्सेस करने के अलावा, मॉडल को कई तरीकों से परिवर्तित, डंप, क्रमबद्ध और निर्यात किया जा सकता है।
!!! टिप "सीरियलाइज़ बनाम डंप" पाइडेंटिक "सीरियलाइज़" और "डंप" शब्दों का परस्पर उपयोग करता है। दोनों एक मॉडल को शब्दकोश या JSON-एन्कोडेड स्ट्रिंग में परिवर्तित करने की प्रक्रिया को संदर्भित करते हैं।
Outside of Pydantic, the word "serialize" usually refers to converting in-memory data into a string or bytes.
However, in the context of Pydantic, there is a very close relationship between converting an object from a more
structured form — such as a Pydantic model, a dataclass, etc. — into a less structured form comprised of
Python built-ins such as dict.
While we could (and on occasion, do) distinguish between these scenarios by using the word "dump" when converting to
primitives and "serialize" when converting to string, for practical purposes, we frequently use the word "serialize"
to refer to both of these situations, even though it does not always imply conversion to a string or bytes.
model.model_dump(...)
¶
??? एपीआई "एपीआई दस्तावेज़ीकरण" pydantic.main.BaseModel.model_dump
यह किसी मॉडल को शब्दकोश में परिवर्तित करने का प्राथमिक तरीका है। उप-मॉडलों को पुनरावर्ती रूप से शब्दकोशों में परिवर्तित किया जाएगा।
!!! ध्यान दें उप-मॉडल को शब्दकोशों में परिवर्तित करने का एक अपवाद यह है कि RootModel
और इसके उपवर्गों में root
फ़ील्ड मान को रैपिंग डिक्शनरी के बिना सीधे डंप किया जाएगा। यह भी पुनरावर्ती रूप से किया जाता है.
!!! नोट आप model.model_dump(...)
आउटपुट में property
और cached_property
डेटा को शामिल करने के लिए गणना किए गए फ़ील्ड का उपयोग कर सकते हैं।
उदाहरण:
from typing import Any, List, Optional
from pydantic import BaseModel, Field, Json
class BarModel(BaseModel):
whatever: int
class FooBarModel(BaseModel):
banana: Optional[float] = 1.1
foo: str = Field(serialization_alias='foo_alias')
bar: BarModel
m = FooBarModel(banana=3.14, foo='hello', bar={'whatever': 123})
# returns a dictionary:
print(m.model_dump())
#> {'banana': 3.14, 'foo': 'hello', 'bar': {'whatever': 123}}
print(m.model_dump(include={'foo', 'bar'}))
#> {'foo': 'hello', 'bar': {'whatever': 123}}
print(m.model_dump(exclude={'foo', 'bar'}))
#> {'banana': 3.14}
print(m.model_dump(by_alias=True))
#> {'banana': 3.14, 'foo_alias': 'hello', 'bar': {'whatever': 123}}
print(
FooBarModel(foo='hello', bar={'whatever': 123}).model_dump(
exclude_unset=True
)
)
#> {'foo': 'hello', 'bar': {'whatever': 123}}
print(
FooBarModel(banana=1.1, foo='hello', bar={'whatever': 123}).model_dump(
exclude_defaults=True
)
)
#> {'foo': 'hello', 'bar': {'whatever': 123}}
print(
FooBarModel(foo='hello', bar={'whatever': 123}).model_dump(
exclude_defaults=True
)
)
#> {'foo': 'hello', 'bar': {'whatever': 123}}
print(
FooBarModel(banana=None, foo='hello', bar={'whatever': 123}).model_dump(
exclude_none=True
)
)
#> {'foo': 'hello', 'bar': {'whatever': 123}}
class Model(BaseModel):
x: List[Json[Any]]
print(Model(x=['{"a": 1}', '[1, 2]']).model_dump())
#> {'x': [{'a': 1}, [1, 2]]}
print(Model(x=['{"a": 1}', '[1, 2]']).model_dump(round_trip=True))
#> {'x': ['{"a":1}', '[1,2]']}
model.model_dump_json(...)
¶
??? एपीआई "एपीआई दस्तावेज़ीकरण" pydantic.main.BaseModel.model_dump_json
.model_dump_json()
विधि एक मॉडल को सीधे JSON-एन्कोडेड स्ट्रिंग पर क्रमबद्ध करती है जो .model_dump()
द्वारा उत्पादित परिणाम के बराबर है।
अधिक जानकारी के लिए तर्क देखें।
!!! नोट पाइडेंटिक आमतौर पर उपयोग किए जाने वाले कई प्रकारों को JSON में क्रमबद्ध कर सकता है जो अन्यथा एक साधारण json.dumps(foobar)
(उदाहरण के लिए datetime
, date
या UUID
) के साथ असंगत होगा।
from datetime import datetime
from pydantic import BaseModel
class BarModel(BaseModel):
whatever: int
class FooBarModel(BaseModel):
foo: datetime
bar: BarModel
m = FooBarModel(foo=datetime(2032, 6, 1, 12, 13, 14), bar={'whatever': 123})
print(m.model_dump_json())
#> {"foo":"2032-06-01T12:13:14","bar":{"whatever":123}}
print(m.model_dump_json(indent=2))
"""
{
"foo": "2032-06-01T12:13:14",
"bar": {
"whatever": 123
}
}
"""
dict(model)
और पुनरावृत्ति¶
पाइडेंटिक मॉडल को dict(model)
उपयोग करके शब्दकोशों में भी परिवर्तित किया जा सकता है, और आप इसका उपयोग करके मॉडल के फ़ील्ड पर पुनरावृति भी कर सकते हैं for field_name, field_value in model:
. इस दृष्टिकोण के साथ कच्चे फ़ील्ड मान वापस कर दिए जाते हैं, इसलिए उप-मॉडल को शब्दकोशों में परिवर्तित नहीं किया जाएगा।
उदाहरण:
from pydantic import BaseModel
class BarModel(BaseModel):
whatever: int
class FooBarModel(BaseModel):
banana: float
foo: str
bar: BarModel
m = FooBarModel(banana=3.14, foo='hello', bar={'whatever': 123})
print(dict(m))
#> {'banana': 3.14, 'foo': 'hello', 'bar': BarModel(whatever=123)}
for name, value in m:
print(f'{name}: {value}')
#> banana: 3.14
#> foo: hello
#> bar: whatever=123
यह भी ध्यान दें कि RootModel
'root'
कुंजी के साथ एक शब्दकोश में परिवर्तित हो जाता है ।
कस्टम सीरियलाइज़र¶
किसी मॉडल को शब्दकोश या JSON में क्रमबद्ध करने के तरीके को अनुकूलित करने के लिए Pydantic कई कार्यात्मक क्रमांकन प्रदान करता है।
क्रमांकन को फ़ील्ड पर @field_serializer
डेकोरेटर का उपयोग करके और मॉडल पर @model_serializer
डेकोरेटर का उपयोग करके अनुकूलित किया जा सकता है।
from datetime import datetime, timedelta, timezone
from typing import Any, Dict
from pydantic import BaseModel, ConfigDict, field_serializer, model_serializer
class WithCustomEncoders(BaseModel):
model_config = ConfigDict(ser_json_timedelta='iso8601')
dt: datetime
diff: timedelta
@field_serializer('dt')
def serialize_dt(self, dt: datetime, _info):
return dt.timestamp()
m = WithCustomEncoders(
dt=datetime(2032, 6, 1, tzinfo=timezone.utc), diff=timedelta(hours=100)
)
print(m.model_dump_json())
#> {"dt":1969660800.0,"diff":"P4DT4H"}
class Model(BaseModel):
x: str
@model_serializer
def ser_model(self) -> Dict[str, Any]:
return {'x': f'serialized {self.x}'}
print(Model(x='test value').model_dump_json())
#> {"x":"serialized test value"}
!!! नोट @field_serializer
डेकोरेटर को विशेष मान '*' पास करके सभी फ़ील्ड पर एक एकल सीरियलाइज़र भी बुलाया जा सकता है।
इसके अलावा, PlainSerializer
और WrapSerializer
आपको क्रमबद्धता के आउटपुट को संशोधित करने के लिए एक फ़ंक्शन का उपयोग करने में सक्षम बनाता है।
दोनों क्रमबद्धकर्ता वैकल्पिक तर्क स्वीकार करते हैं जिनमें शामिल हैं:
return_type
फ़ंक्शन के लिए रिटर्न प्रकार निर्दिष्ट करता है। यदि छोड़ दिया जाए तो इसका अनुमान प्रकार एनोटेशन से लगाया जाएगा।when_used
निर्दिष्ट करता है कि इस सीरिएलाइज़र का उपयोग कब किया जाना चाहिए। 'हमेशा', 'unless-none', 'json', और 'json-unless-none' मानों वाली एक स्ट्रिंग स्वीकार करता है। डिफ़ॉल्ट 'हमेशा'.
PlainSerializer
क्रमबद्धता के आउटपुट को संशोधित करने के लिए एक सरल फ़ंक्शन का उपयोग करता है।
from typing_extensions import Annotated
from pydantic import BaseModel
from pydantic.functional_serializers import PlainSerializer
FancyInt = Annotated[
int, PlainSerializer(lambda x: f'{x:,}', return_type=str, when_used='json')
]
class MyModel(BaseModel):
x: FancyInt
print(MyModel(x=1234).model_dump())
#> {'x': 1234}
print(MyModel(x=1234).model_dump(mode='json'))
#> {'x': '1,234'}
WrapSerializer
एक हैंडलर फ़ंक्शन के साथ कच्चे इनपुट प्राप्त करता है जो मानक क्रमबद्धता तर्क लागू करता है, और परिणामी मूल्य को क्रमबद्धता के अंतिम आउटपुट के रूप में वापस करने से पहले संशोधित कर सकता है।
from typing import Any
from typing_extensions import Annotated
from pydantic import BaseModel, SerializerFunctionWrapHandler
from pydantic.functional_serializers import WrapSerializer
def ser_wrap(v: Any, nxt: SerializerFunctionWrapHandler) -> str:
return f'{nxt(v + 1):,}'
FancyInt = Annotated[int, WrapSerializer(ser_wrap, when_used='json')]
class MyModel(BaseModel):
x: FancyInt
print(MyModel(x=1234).model_dump())
#> {'x': 1234}
print(MyModel(x=1234).model_dump(mode='json'))
#> {'x': '1,235'}
किसी मॉडल को डंप करते समय रिटर्न प्रकार को ओवरराइड करना¶
जबकि .model_dump()
का रिटर्न मान आमतौर पर dict[str, Any]
के रूप में वर्णित किया जा सकता है, @model_serializer
के उपयोग के माध्यम से आप वास्तव में इसे एक ऐसा मान लौटा सकते हैं जो इस हस्ताक्षर से मेल नहीं खाता है:
from pydantic import BaseModel, model_serializer
class Model(BaseModel):
x: str
@model_serializer
def ser_model(self) -> str:
return self.x
print(Model(x='not a dict').model_dump())
#> not a dict
यदि आप ऐसा करना चाहते हैं और फिर भी इस विधि के लिए उचित टाइप-चेकिंग प्राप्त करना चाहते हैं, तो आप if TYPE_CHECKING:
ब्लॉक में .model_dump()
को ओवरराइड कर सकते हैं:
from typing import TYPE_CHECKING, Any
from typing_extensions import Literal
from pydantic import BaseModel, model_serializer
class Model(BaseModel):
x: str
@model_serializer
def ser_model(self) -> str:
return self.x
if TYPE_CHECKING:
# Ensure type checkers see the correct return type
def model_dump(
self,
*,
mode: Literal['json', 'python'] | str = 'python',
include: Any = None,
exclude: Any = None,
by_alias: bool = False,
exclude_unset: bool = False,
exclude_defaults: bool = False,
exclude_none: bool = False,
round_trip: bool = False,
warnings: bool = True,
) -> str: ...
यह ट्रिक वास्तव में इसी उद्देश्य के लिए RootModel
में उपयोग की जाती है।
उपवर्गों को क्रमबद्ध करना¶
मानक प्रकार के उपवर्ग¶
मानक प्रकार के उपवर्ग स्वचालित रूप से उनके सुपर-वर्गों की तरह डंप हो जाते हैं:
from datetime import date, timedelta
from typing import Any, Type
from pydantic_core import core_schema
from pydantic import BaseModel, GetCoreSchemaHandler
class DayThisYear(date):
"""
Contrived example of a special type of date that
takes an int and interprets it as a day in the current year
"""
@classmethod
def __get_pydantic_core_schema__(
cls, source: Type[Any], handler: GetCoreSchemaHandler
) -> core_schema.CoreSchema:
return core_schema.no_info_after_validator_function(
cls.validate,
core_schema.int_schema(),
serialization=core_schema.format_ser_schema('%Y-%m-%d'),
)
@classmethod
def validate(cls, v: int):
return date(2023, 1, 1) + timedelta(days=v)
class FooModel(BaseModel):
date: DayThisYear
m = FooModel(date=300)
print(m.model_dump_json())
#> {"date":"2023-10-28"}
BaseModel
, डेटाक्लास, TypedDict
के क्षेत्रों के लिए उपवर्ग उदाहरण¶
उन फ़ील्ड का उपयोग करते समय जिनके एनोटेशन स्वयं संरचना-जैसे प्रकार होते हैं (उदाहरण के लिए, BaseModel
उपवर्ग, डेटाक्लास इत्यादि), डिफ़ॉल्ट व्यवहार विशेषता मान को क्रमबद्ध करना है जैसे कि यह एनोटेटेड प्रकार का एक उदाहरण था, भले ही यह एक उपवर्ग हो। अधिक विशेष रूप से, केवल एनोटेटेड प्रकार के फ़ील्ड को डंप किए गए ऑब्जेक्ट में शामिल किया जाएगा:
from pydantic import BaseModel
class User(BaseModel):
name: str
class UserLogin(User):
password: str
class OuterModel(BaseModel):
user: User
user = UserLogin(name='pydantic', password='hunter2')
m = OuterModel(user=user)
print(m)
#> user=UserLogin(name='pydantic', password='hunter2')
print(m.model_dump()) # note: the password field is not included
#> {'user': {'name': 'pydantic'}}
!!! चेतावनी "माइग्रेशन चेतावनी" यह व्यवहार पाइडेंटिक V1 में काम करने के तरीके से अलग है, जहां हम मॉडल को डिक्ट्स में पुनरावर्ती रूप से डंप करते समय हमेशा सभी (उपवर्ग) फ़ील्ड शामिल करेंगे। व्यवहार में इस बदलाव के पीछे प्रेरणा यह है कि इससे यह सुनिश्चित करने में मदद मिलती है कि आप सटीक रूप से जानते हैं कि क्रमबद्ध करते समय कौन से फ़ील्ड शामिल किए जा सकते हैं, भले ही ऑब्जेक्ट को इंस्टेंट करते समय उपवर्ग पारित हो जाएं। विशेष रूप से, यह रहस्य जैसी संवेदनशील जानकारी को उपवर्गों के फ़ील्ड के रूप में जोड़ते समय आश्चर्य को रोकने में मदद कर सकता है।
डक-टाइपिंग के साथ क्रमबद्ध करना 🦆¶
!!! प्रश्न "डक टाइपिंग के साथ क्रमबद्धता क्या है?"
Duck-typing serialization is the behavior of serializing an object based on the fields present in the object itself,
rather than the fields present in the schema of the object. This means that when an object is serialized, fields present in
a subclass, but not in the original schema, will be included in the serialized output.
This behavior was the default in Pydantic V1, but was changed in V2 to help ensure that you know precisely which
fields would be included when serializing, even if subclasses get passed when instantiating the object. This helps
prevent security risks when serializing subclasses with sensitive information, for example.
यदि आप v1-शैली डक-टाइपिंग क्रमांकन व्यवहार चाहते हैं, तो आप रनटाइम सेटिंग का उपयोग कर सकते हैं, या अलग-अलग प्रकारों को एनोटेट कर सकते हैं।
- फ़ील्ड/प्रकार स्तर:
SerializeAsAny
एनोटेशन का उपयोग करें - रनटाइम स्तर:
model_dump()
याmodel_dump_json()
कॉल करते समयserialize_as_any
ध्वज का उपयोग करें
हम नीचे इन विकल्पों पर अधिक विस्तार से चर्चा करते हैं:
SerializeAsAny
एनोटेशन:¶
यदि आप डक-टाइपिंग क्रमांकन व्यवहार चाहते हैं, तो इसे एक प्रकार पर SerializeAsAny
एनोटेशन का उपयोग करके किया जा सकता है:
from pydantic import BaseModel, SerializeAsAny
class User(BaseModel):
name: str
class UserLogin(User):
password: str
class OuterModel(BaseModel):
as_any: SerializeAsAny[User]
as_user: User
user = UserLogin(name='pydantic', password='password')
print(OuterModel(as_any=user, as_user=user).model_dump())
"""
{
'as_any': {'name': 'pydantic', 'password': 'password'},
'as_user': {'name': 'pydantic'},
}
"""
जब किसी फ़ील्ड को SerializeAsAny[<SomeType>]
के रूप में एनोटेट किया जाता है, तो सत्यापन व्यवहार वैसा ही होगा जैसे कि इसे <SomeType>
के रूप में एनोटेट किया गया था, और mypy जैसे टाइप-चेकर्स विशेषता को उचित प्रकार के रूप में भी मानेंगे। लेकिन क्रमबद्ध करते समय, फ़ील्ड को क्रमबद्ध किया जाएगा जैसे कि फ़ील्ड के लिए प्रकार का संकेत Any
था, जहां से नाम आता है।
serialize_as_any
रनटाइम सेटिंग¶
serialize_as_any
रनटाइम सेटिंग का उपयोग डक टाइप क्रमबद्धता व्यवहार के साथ या उसके बिना मॉडल डेटा को क्रमबद्ध करने के लिए किया जा सकता है। serialize_as_any
BaseModel
s और RootModel
s के model_dump()
और model_dump_json
तरीकों के लिए एक कीवर्ड तर्क के रूप में पारित किया जा सकता है। इसे TypeAdapter
एस के dump_python()
और dump_json()
तरीकों के लिए एक कीवर्ड तर्क के रूप में भी पारित किया जा सकता है।
यदि serialize_as_any
को True
पर सेट किया गया है, तो मॉडल को डक टाइप सीरियलाइज़ेशन व्यवहार का उपयोग करके क्रमबद्ध किया जाएगा, जिसका अर्थ है कि मॉडल स्कीमा को अनदेखा कर देगा और इसके बजाय ऑब्जेक्ट से स्वयं पूछेगा कि इसे कैसे क्रमबद्ध किया जाना चाहिए। विशेष रूप से, इसका मतलब यह है कि जब मॉडल उपवर्गों को क्रमबद्ध किया जाता है, तो उपवर्ग में मौजूद फ़ील्ड शामिल किए जाएंगे, लेकिन मूल स्कीमा में नहीं।
यदि serialize_as_any
False
(जो कि डिफ़ॉल्ट है) पर सेट किया गया है, तो मॉडल को स्कीमा का उपयोग करके क्रमबद्ध किया जाएगा, जिसका अर्थ है कि उपवर्ग में मौजूद फ़ील्ड लेकिन मूल स्कीमा में मौजूद फ़ील्ड को अनदेखा नहीं किया जाएगा।
!!! प्रश्न "यह झंडा उपयोगी क्यों है?" कभी-कभी, आप यह सुनिश्चित करना चाहते हैं कि उपवर्गों में चाहे जो भी फ़ील्ड जोड़े गए हों, क्रमबद्ध ऑब्जेक्ट में केवल मूल प्रकार की परिभाषा में सूचीबद्ध फ़ील्ड होंगे। यह उपयोगी हो सकता है यदि आप किसी उपवर्ग में password: str
फ़ील्ड जैसा कुछ जोड़ते हैं जिसे आप क्रमबद्ध आउटपुट में गलती से शामिल नहीं करना चाहते हैं।
उदाहरण के लिए:
from pydantic import BaseModel
class User(BaseModel):
name: str
class UserLogin(User):
password: str
class OuterModel(BaseModel):
user1: User
user2: User
user = UserLogin(name='pydantic', password='password')
outer_model = OuterModel(user1=user, user2=user)
print(outer_model.model_dump(serialize_as_any=True)) # (1)!
"""
{
'user1': {'name': 'pydantic', 'password': 'password'},
'user2': {'name': 'pydantic', 'password': 'password'},
}
"""
print(outer_model.model_dump(serialize_as_any=False)) # (2)!
#> {'user1': {'name': 'pydantic'}, 'user2': {'name': 'pydantic'}}
serialize_as_any
True
पर सेट करने पर, परिणाम V1 से मेल खाता है।serialize_as_any
False
(V2 डिफ़ॉल्ट) पर सेट करने से, उपवर्ग पर मौजूद फ़ील्ड, लेकिन आधार वर्ग नहीं, क्रमबद्धता में शामिल नहीं होते हैं।
यह सेटिंग नेस्टेड और पुनरावर्ती पैटर्न के साथ भी प्रभावी होती है। उदाहरण के लिए:
from typing import List
from pydantic import BaseModel
class User(BaseModel):
name: str
friends: List['User']
class UserLogin(User):
password: str
class OuterModel(BaseModel):
user: User
user = UserLogin(
name='samuel',
password='pydantic-pw',
friends=[UserLogin(name='sebastian', password='fastapi-pw', friends=[])],
)
print(OuterModel(user=user).model_dump(serialize_as_any=True)) # (1)!
"""
{
'user': {
'name': 'samuel',
'friends': [
{'name': 'sebastian', 'friends': [], 'password': 'fastapi-pw'}
],
'password': 'pydantic-pw',
}
}
"""
print(OuterModel(user=user).model_dump(serialize_as_any=False)) # (2)!
"""
{'user': {'name': 'samuel', 'friends': [{'name': 'sebastian', 'friends': []}]}}
"""
- यहां तक कि नेस्टेड
User
मॉडल उदाहरणों कोUser
उपवर्गों के लिए अद्वितीय फ़ील्ड के साथ डंप किया जाता है। - यहां तक कि नेस्टेड
User
मॉडल उदाहरणों कोUser
उपवर्गों के लिए अद्वितीय फ़ील्ड के बिना डंप कर दिया जाता है।
!!! नोट serialize_as_any
रनटाइम ध्वज का व्यवहार लगभग SerializeAsAny
एनोटेशन के व्यवहार के समान है। कुछ बारीक अंतर हैं जिन्हें हम दूर करने के लिए काम कर रहे हैं, लेकिन अधिकांश भाग के लिए, आप दोनों से समान व्यवहार की उम्मीद कर सकते हैं। इस सक्रिय मुद्दे में अंतर के बारे में और देखें
serialize_as_any
डिफ़ॉल्ट को ओवरराइड करना (गलत)¶
आप BaseModel
के एक उपवर्ग को कॉन्फ़िगर करके serialize_as_any
के लिए डिफ़ॉल्ट सेटिंग को ओवरराइड कर सकते हैं जो serialize_as_any
तर्क के लिए डिफ़ॉल्ट को model_dump()
और model_dump_json()
पर ओवरराइड करता है, और फिर उसे किसी भी मॉडल के लिए बेस क्लास ( pydantic.BaseModel
के बजाय) के रूप में उपयोग करें। यह डिफ़ॉल्ट व्यवहार रखना चाहते हैं.
उदाहरण के लिए, यदि आप डिफ़ॉल्ट रूप से डक-टाइपिंग क्रमबद्धता का उपयोग करना चाहते हैं तो आप निम्न कार्य कर सकते हैं:
from typing import Any, Dict
from pydantic import BaseModel, SecretStr
class MyBaseModel(BaseModel):
def model_dump(self, **kwargs) -> Dict[str, Any]:
return super().model_dump(serialize_as_any=True, **kwargs)
def model_dump_json(self, **kwargs) -> str:
return super().model_dump_json(serialize_as_any=True, **kwargs)
class User(MyBaseModel):
name: str
class UserInfo(User):
password: SecretStr
class OuterModel(MyBaseModel):
user: User
u = OuterModel(user=UserInfo(name='John', password='secret_pw'))
print(u.model_dump_json()) # (1)!
#> {"user":{"name":"John","password":"**********"}}
- डिफ़ॉल्ट रूप से,
model_dump_json
डक-टाइपिंग क्रमांकन व्यवहार का उपयोग करेगा, जिसका अर्थ है किpassword
फ़ील्ड आउटपुट में शामिल है।
pickle.dumps(model)
¶
पाइडेंटिक मॉडल कुशल अचार और अचार निकालने का समर्थन करते हैं।
import pickle
from pydantic import BaseModel
class FooBarModel(BaseModel):
a: str
b: int
m = FooBarModel(a='hello', b=123)
print(m)
#> a='hello' b=123
data = pickle.dumps(m)
print(data[:20])
#> b'\x80\x04\x95\x95\x00\x00\x00\x00\x00\x00\x00\x8c\x08__main_'
m2 = pickle.loads(data)
print(m2)
#> a='hello' b=123
उन्नत शामिल करें और बहिष्कृत करें¶
model_dump
और model_dump_json
तरीकों का समर्थन उन तर्कों को include
और exclude
जो या तो सेट या शब्दकोश हो सकते हैं। यह निर्यात किए जाने वाले फ़ील्ड के नेस्टेड चयन की अनुमति देता है:
from pydantic import BaseModel, SecretStr
class User(BaseModel):
id: int
username: str
password: SecretStr
class Transaction(BaseModel):
id: str
user: User
value: int
t = Transaction(
id='1234567890',
user=User(id=42, username='JohnDoe', password='hashedpassword'),
value=9876543210,
)
# using a set:
print(t.model_dump(exclude={'user', 'value'}))
#> {'id': '1234567890'}
# using a dict:
print(t.model_dump(exclude={'user': {'username', 'password'}, 'value': True}))
#> {'id': '1234567890', 'user': {'id': 42}}
print(t.model_dump(include={'id': True, 'user': {'id'}}))
#> {'id': '1234567890', 'user': {'id': 42}}
True
इंगित करता है कि हम संपूर्ण कुंजी को बाहर करना या शामिल करना चाहते हैं, जैसे कि हमने इसे एक सेट में शामिल किया हो। यह किसी भी गहराई स्तर पर किया जा सकता है।
किसी सूची या उपमॉडल या शब्दकोशों के टुपल से फ़ील्ड को शामिल या बाहर करते समय विशेष सावधानी बरतनी चाहिए। इस परिदृश्य में, model_dump
और संबंधित विधियां तत्व-वार समावेशन या बहिष्करण के लिए पूर्णांक कुंजियों की अपेक्षा करती हैं। किसी सूची या टुपल के प्रत्येक सदस्य से किसी फ़ील्ड को बाहर करने के लिए, शब्दकोश कुंजी '__all__'
उपयोग किया जा सकता है, जैसा कि यहां दिखाया गया है:
import datetime
from typing import List
from pydantic import BaseModel, SecretStr
class Country(BaseModel):
name: str
phone_code: int
class Address(BaseModel):
post_code: int
country: Country
class CardDetails(BaseModel):
number: SecretStr
expires: datetime.date
class Hobby(BaseModel):
name: str
info: str
class User(BaseModel):
first_name: str
second_name: str
address: Address
card_details: CardDetails
hobbies: List[Hobby]
user = User(
first_name='John',
second_name='Doe',
address=Address(
post_code=123456, country=Country(name='USA', phone_code=1)
),
card_details=CardDetails(
number='4212934504460000', expires=datetime.date(2020, 5, 1)
),
hobbies=[
Hobby(name='Programming', info='Writing code and stuff'),
Hobby(name='Gaming', info='Hell Yeah!!!'),
],
)
exclude_keys = {
'second_name': True,
'address': {'post_code': True, 'country': {'phone_code'}},
'card_details': True,
# You can exclude fields from specific members of a tuple/list by index:
'hobbies': {-1: {'info'}},
}
include_keys = {
'first_name': True,
'address': {'country': {'name'}},
'hobbies': {0: True, -1: {'name'}},
}
# would be the same as user.model_dump(exclude=exclude_keys) in this case:
print(user.model_dump(include=include_keys))
"""
{
'first_name': 'John',
'address': {'country': {'name': 'USA'}},
'hobbies': [
{'name': 'Programming', 'info': 'Writing code and stuff'},
{'name': 'Gaming'},
],
}
"""
# To exclude a field from all members of a nested list or tuple, use "__all__":
print(user.model_dump(exclude={'hobbies': {'__all__': {'info'}}}))
"""
{
'first_name': 'John',
'second_name': 'Doe',
'address': {
'post_code': 123456,
'country': {'name': 'USA', 'phone_code': 1},
},
'card_details': {
'number': SecretStr('**********'),
'expires': datetime.date(2020, 5, 1),
},
'hobbies': [{'name': 'Programming'}, {'name': 'Gaming'}],
}
"""
यही बात model_dump_json
विधि के लिए भी लागू होती है।
मॉडल- और फ़ील्ड-स्तर पर शामिल करें और बहिष्कृत करें¶
स्पष्ट तर्कों के अलावा, model_dump
और model_dump_json
विधियों को शामिल exclude
और include
, हम Field
कंस्ट्रक्टर को सीधे exclude: bool
तर्क भी पास कर सकते हैं:
फ़ील्ड कंस्ट्रक्टर ( Field(..., exclude=True)
) पर exclude
सेट करना model_dump
और model_dump_json
पर exclude
/ include
पर प्राथमिकता लेता है:
from pydantic import BaseModel, Field, SecretStr
class User(BaseModel):
id: int
username: str
password: SecretStr = Field(..., exclude=True)
class Transaction(BaseModel):
id: str
value: int = Field(exclude=True)
t = Transaction(
id='1234567890',
value=9876543210,
)
print(t.model_dump())
#> {'id': '1234567890'}
print(t.model_dump(include={'id': True, 'value': True})) # (1)!
#> {'id': '1234567890'}
value
आउटपुट से बाहर रखा गया है क्योंकि इसेField
में शामिल नहीं किया गया है।
ऐसा कहा जा रहा है कि, फ़ील्ड कंस्ट्रक्टर ( Field(..., exclude=True)
) पर exclude
सेटिंग model_dump
और model_dump_json
पर exclude_unset
, exclude_none
, और exclude_default
पैरामीटर पर प्राथमिकता नहीं लेती है:
from typing import Optional
from pydantic import BaseModel, Field
class Person(BaseModel):
name: str
age: Optional[int] = Field(None, exclude=False)
person = Person(name='Jeremy')
print(person.model_dump())
#> {'name': 'Jeremy', 'age': None}
print(person.model_dump(exclude_none=True)) # (1)!
#> {'name': 'Jeremy'}
print(person.model_dump(exclude_unset=True)) # (2)!
#> {'name': 'Jeremy'}
print(person.model_dump(exclude_defaults=True)) # (3)!
#> {'name': 'Jeremy'}
age
आउटपुट से बाहर रखा गया है क्योंकिexclude_none
True
पर सेट किया गया था, औरage
None
है।age
आउटपुट से बाहर रखा गया है क्योंकिexclude_unset
True
पर सेट किया गया था, और पर्सन कंस्ट्रक्टर मेंage
सेट नहीं की गई थी।age
आउटपुट से बाहर रखा गया है क्योंकिexclude_defaults
True
पर सेट किया गया था, औरage
None
का डिफ़ॉल्ट मान लेती है।
क्रमांकन प्रसंग¶
आप एक संदर्भ ऑब्जेक्ट को क्रमांकन विधियों में पास कर सकते हैं जिसे info
तर्क से सजाए गए क्रमांकन कार्यों तक पहुँचा जा सकता है। यह तब उपयोगी होता है जब आपको रनटाइम के दौरान क्रमांकन व्यवहार को गतिशील रूप से अद्यतन करने की आवश्यकता होती है। उदाहरण के लिए, यदि आप चाहते हैं कि किसी फ़ील्ड को अनुमत मानों के गतिशील रूप से नियंत्रणीय सेट के आधार पर डंप किया जाए, तो अनुमत मानों को संदर्भ के अनुसार पास करके ऐसा किया जा सकता है:
from pydantic import BaseModel, SerializationInfo, field_serializer
class Model(BaseModel):
text: str
@field_serializer('text')
def remove_stopwords(self, v: str, info: SerializationInfo):
context = info.context
if context:
stopwords = context.get('stopwords', set())
v = ' '.join(w for w in v.split() if w.lower() not in stopwords)
return v
model = Model.model_construct(**{'text': 'This is an example document'})
print(model.model_dump()) # no context
#> {'text': 'This is an example document'}
print(model.model_dump(context={'stopwords': ['this', 'is', 'an']}))
#> {'text': 'example document'}
print(model.model_dump(context={'stopwords': ['document']}))
#> {'text': 'This is an example'}
इसी तरह, आप सत्यापन के लिए एक संदर्भ का उपयोग कर सकते हैं।
model_copy(...)
¶
??? एपीआई "एपीआई दस्तावेज़ीकरण" pydantic.main.BaseModel.model_copy
model_copy()
मॉडलों को डुप्लिकेट करने की अनुमति देता है (वैकल्पिक अपडेट के साथ), जो जमे हुए मॉडल के साथ काम करते समय विशेष रूप से उपयोगी होता है।
उदाहरण:
from pydantic import BaseModel
class BarModel(BaseModel):
whatever: int
class FooBarModel(BaseModel):
banana: float
foo: str
bar: BarModel
m = FooBarModel(banana=3.14, foo='hello', bar={'whatever': 123})
print(m.model_copy(update={'banana': 0}))
#> banana=0 foo='hello' bar=BarModel(whatever=123)
print(id(m.bar) == id(m.model_copy().bar))
#> True
# normal copy gives the same object reference for bar
print(id(m.bar) == id(m.model_copy(deep=True).bar))
#> False
# deep copy gives a new object reference for `bar`
本文总阅读量次