Search code examples
python-3.xpydantic

How to ensure attribute doesnt exist if None when using pydantic basemodel


If one attribute is None, then that attribute should not even exist. So I have code written as follows:

Using default OOPs concepts:

class C(object):
    def __init__(self, c, t=None):
        self.c = c
        if t:
            self.t = t

c1 = C(c=1, t=2)
print(c1.t) #prints 2
c1 = C(c=1)
print(c1.t) #throws error

My intention is to use Pydantic instead. I have come up with the following:

class C(BaseModel):
    c: int
    def __init__(self, **data):
        if data.get("t"):
            data["t"] = data.get("t")
        super().__init__(**data)


c1 = C(c=1, t=2)
print(c1.t) #throws error
c1 = C(c=1)
print(c1.t) #throws error

I have the following:

class C(BaseModel):
    c: int
    model_config = ConfigDict(extra='allow')

But this would allow additional arguments. I only want to restrict to one more with a clearly defined name


Solution

  • You should add model_config = ConfigDict(extra='allow') to your model to allow using extra fields.

    And in __init__ method you should remove t key if it exists in the data dict and is equal to None. And remove all extra fields except t as well.

    from pydantic import BaseModel, ConfigDict
    
    class C(BaseModel):
        model_config = ConfigDict(extra='allow')
        c: int
        def __init__(self, **data):
            for k in dict(data).keys():
                if k == "t":
                    if data.get("t") is None:
                        data.pop("t")
                elif k not in self.__class__.model_fields.keys():
                    data.pop(k)
    
            super().__init__(**data)
    
    
    c1 = C(c=1, t=2)
    print(c1.t) # prints 2
    
    
    c1 = C(c=1)
    try:
        print(c1.t) # throws error
    except AttributeError as e:
        print(e)
    
    
    c1 = C(c=1, t=None)
    try:
        print(c1.t) # throws error
    except AttributeError as e:
        print(e)
    
    
    c1 = C(c=1, tt=2)
    try:
        print(c1.tt) # throws error
    except AttributeError as e:
        print(e)