Rahul
Rahul

Reputation: 127

How to get values from nested pydantic classes?

class mail(BaseModel):
    mailid: int
    email: str
    
class User(BaseModel):
    id: int
    name: str
    mails: List[mail]

data = {
    'id': 123,
    'name': 'Jane Doe',
    'mails':[
        {'mailid':1,'email':'[email protected]'}, 
        {'mailid':2,'email':'[email protected]'}
    ]
}
    
userobj = User(**data)

How to get the value of email in mail class or mailid from mail class?

When I try to use print(mail.email) it throws error as

AttributeError: type object 'mail' has no attribute 'email'

When I use this got error too

print(userobj.mails.email)
AttributeError: 'list' object has no attribute 'email'

When I use this I get data as follows

print(userobj.mails)
[mail(mailid=1, email='[email protected]'), mail(mailid=2, email='[email protected]')]

My desire output must be when I want to print email I must get '[email protected]','[email protected]'

Upvotes: 2

Views: 2693

Answers (2)

Paul P
Paul P

Reputation: 3917

It looks like you are trying to access the class rather than the instance.

Here's one way of doing it:

from pydantic import BaseModel
from typing import List

class Mail(BaseModel):
    mailid: int
    email: str

one_mail = {"mailid": 1, "email": "[email protected]"}

mail = Mail(**one_mail)

print(mail)
# mailid=1 email='[email protected]'

With that in place, let's adapt the User model:

class User(BaseModel):
    id: int
    name: str
    mails: List[Mail]

data = {
    "id": 123, 
    "name": "Jane Doe",
    "mails":[
        {"mailid": 1, "email": "[email protected]"}, 
        {"mailid": 2, "email": "[email protected]"}
    ]
}

userobj = User(**data)

print(userobj.mails)
# [Mail(mailid=1, email='[email protected]'), Mail(mailid=2, email='[email protected]')]

If you only need one of the email addresses, you need to specify which one, e.g.:

print(userobj.mails[0].email)
# [email protected]

In order to get a list of all email addresses, you need to iterate over the mails, e.g.:

print([mail.email for mail in userobj.mails])
# ['[email protected]', '[email protected]']

An as a side note: Pydantic supports email string validation.

Upvotes: 4

Pavel Vergeev
Pavel Vergeev

Reputation: 3380

The error

AttributeError: 'list' object has no attribute 'email'

means you are accessing an attribute of the mails list, not mail object.

You should pick the object from the list first using an index:

print(userobj.mails[0].email)

And, if you want every email of every mails instance, do

print([mail.email for mail in userobj.mails])

Upvotes: 2

Related Questions