Is it bad practice to include non-validating methods in a pydantic model?
Question:
I’m using pydantic 1.3 to validate models for an API I am writing.
Is it common/good practice to include arbitrary methods in a class that inherits from pydantic.BaseModel
?
I need some helper methods associated with the objects and I am trying to decide whether I need a "handler" class. These models are being converted to JSON and sent to a restful service that I am also writing.
My model looks like this:
class Foo(pydantic.BaseModel):
name: str
bar: int
baz: int
Is it poor practice to do something like:
class Foo(pydantic.BaseModel):
name: str
bar: int
baz: int
def add_one(self):
self.bar += 1
It makes some sense to me, but I can’t find an example of anyone doing this.
Answers:
Yes, it’s fine. We should probably document it.
The only problem comes when you have a field name which conflicts with the method, but that’s not a problem if you know what your data looks like. Also, it’s possible to over object orient your code, but you’re a long way from that.
I have a similar question –
the following works well in the way defined above:
from pydantic import BaseModel
import pathlib
import typing
class BaseModel(BaseModel):
def file(self: typing.Type[BaseModel], path: pathlib.Path, **json_kwargs):
"""
this is a method that is added to the pydantic BaseModel within AutoUi using
"setattr".
Example:
```setattr(model, 'file', file)```
Args:
self (pydantic.BaseModel): instance
path (pathlib.Path): to write file to
"""
if "indent" not in json_kwargs.keys():
json_kwargs.update({"indent": 4})
path.write_text(self.json(**json_kwargs), encoding="utf-8")
class DataFrameCols(BaseModel):
string: str = "string"
integer: int = 1
floater: float = 1.2
something_else: float = 1
t = DataFrameCols()
t.file(pathlib.Path("test.json"))
# file successfully saved
but I’d like to add the method to the class on-the-fly.
e.g.
def foo():
print("foo")
class A:
def bar(self):
print("bar")
def barFighters(self):
print("barFighters")
a = A()
a.barFighters = types.MethodType(barFighters, a)
a.barFighters()
>>> "barFighters"
if I try and do this though, I get a ValueError…
from pydantic import BaseModel
class DataFrameCols(BaseModel):
string: str = Field("string", aui_column_width=100)
integer: int = Field(1, aui_column_width=80)
floater: float = Field(3.1415, aui_column_width=70, aui_sig_fig=3)
something_else: float = Field(324, aui_column_width=100)
def file(self: typing.Type[BaseModel], path: pathlib.Path, **json_kwargs):
"""
this is a method that is added to the pydantic BaseModel within AutoUi using
"setattr".
Example:
```setattr(model, 'file', file)```
Args:
self (pydantic.BaseModel): instance
path (pathlib.Path): to write file to
"""
if "indent" not in json_kwargs.keys():
json_kwargs.update({"indent": 4})
path.write_text(self.json(**json_kwargs), encoding="utf-8")
t = DataFrameCols()
t.file = types.MethodType(file, t)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Input In [50], in <cell line: 27>()
24 path.write_text(self.json(**json_kwargs), encoding="utf-8")
26 t = DataFrameCols()
---> 27 t.file = types.MethodType(file, t)
File ~/miniconda3/envs/ipyautoui-dev/lib/python3.9/site-packages/pydantic/main.py:347, in pydantic.main.BaseModel.__setattr__()
ValueError: "DataFrameCols" object has no field "file"
is there a way around this?
many thanks
I’m using pydantic 1.3 to validate models for an API I am writing.
Is it common/good practice to include arbitrary methods in a class that inherits from pydantic.BaseModel
?
I need some helper methods associated with the objects and I am trying to decide whether I need a "handler" class. These models are being converted to JSON and sent to a restful service that I am also writing.
My model looks like this:
class Foo(pydantic.BaseModel):
name: str
bar: int
baz: int
Is it poor practice to do something like:
class Foo(pydantic.BaseModel):
name: str
bar: int
baz: int
def add_one(self):
self.bar += 1
It makes some sense to me, but I can’t find an example of anyone doing this.
Yes, it’s fine. We should probably document it.
The only problem comes when you have a field name which conflicts with the method, but that’s not a problem if you know what your data looks like. Also, it’s possible to over object orient your code, but you’re a long way from that.
I have a similar question –
the following works well in the way defined above:
from pydantic import BaseModel
import pathlib
import typing
class BaseModel(BaseModel):
def file(self: typing.Type[BaseModel], path: pathlib.Path, **json_kwargs):
"""
this is a method that is added to the pydantic BaseModel within AutoUi using
"setattr".
Example:
```setattr(model, 'file', file)```
Args:
self (pydantic.BaseModel): instance
path (pathlib.Path): to write file to
"""
if "indent" not in json_kwargs.keys():
json_kwargs.update({"indent": 4})
path.write_text(self.json(**json_kwargs), encoding="utf-8")
class DataFrameCols(BaseModel):
string: str = "string"
integer: int = 1
floater: float = 1.2
something_else: float = 1
t = DataFrameCols()
t.file(pathlib.Path("test.json"))
# file successfully saved
but I’d like to add the method to the class on-the-fly.
e.g.
def foo():
print("foo")
class A:
def bar(self):
print("bar")
def barFighters(self):
print("barFighters")
a = A()
a.barFighters = types.MethodType(barFighters, a)
a.barFighters()
>>> "barFighters"
if I try and do this though, I get a ValueError…
from pydantic import BaseModel
class DataFrameCols(BaseModel):
string: str = Field("string", aui_column_width=100)
integer: int = Field(1, aui_column_width=80)
floater: float = Field(3.1415, aui_column_width=70, aui_sig_fig=3)
something_else: float = Field(324, aui_column_width=100)
def file(self: typing.Type[BaseModel], path: pathlib.Path, **json_kwargs):
"""
this is a method that is added to the pydantic BaseModel within AutoUi using
"setattr".
Example:
```setattr(model, 'file', file)```
Args:
self (pydantic.BaseModel): instance
path (pathlib.Path): to write file to
"""
if "indent" not in json_kwargs.keys():
json_kwargs.update({"indent": 4})
path.write_text(self.json(**json_kwargs), encoding="utf-8")
t = DataFrameCols()
t.file = types.MethodType(file, t)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Input In [50], in <cell line: 27>()
24 path.write_text(self.json(**json_kwargs), encoding="utf-8")
26 t = DataFrameCols()
---> 27 t.file = types.MethodType(file, t)
File ~/miniconda3/envs/ipyautoui-dev/lib/python3.9/site-packages/pydantic/main.py:347, in pydantic.main.BaseModel.__setattr__()
ValueError: "DataFrameCols" object has no field "file"
is there a way around this?
many thanks