Eric
Eric

Reputation: 31

How to achieve a bidirectional implementation from a unidirectional structure with pydantic models without fetching from a database?

I am conflicted on the best design approach to implement for my project. still a developing back-end dev, Looking for some insights!

Goal: Achieve a bidirectional implementation from a unidirectional structure with pydantic models without fetching from the database.

Problem: I have a unidirectional structure for my Pydantic model, but I want to achieve a bidirectional implementation to access base model attributes from my ‘bottom-most’ (lack for a better word) model without fetching from my database or directly referencing the base model.

Here's an example code:

data = { ... }

class Transactions(BaseModel):
    transaction_id: int

class Receipt(BaseModel):
    receipt_id: int
    transactions: List[Transactions]

transaction_one = Receipt(**data)

I want to access receipt_id by referencing an instance of transactions, that is, transaction_one.receipt_id

Possible Solutions:

  1. Pass in my Base Model to my function and reference the attribute directly.
  2. Assign the Base Model attribute to a variable and pass that into my function.

Upvotes: 0

Views: 57

Answers (1)

Schorsch
Schorsch

Reputation: 541

I think the "correct" solution depends on what exactly it is you want to do and what your limitations / prerequisites are. A possible solution could be to also give Transaction a receipt_id that you then assign on assigning it to a receipt. But it really depends on how you intend to create and update your objects.

from pydantic import BaseModel, validator
from typing import Optional, List, Dict, Any

data = { ... }

class Transactions(BaseModel):
    transaction_id: int
    receipt_id: Optional[int] = None

class Receipt(BaseModel):
    receipt_id: int
    transactions: List[Transactions]
    
    @validator("transactions")
    def add_receipt_id(cls, value: List[Transactions], values: Dict[str, Any]) -> List[Transactions]:
        for transaction in value:
            # only replace receipt_id if it is None, depends on your usecase
            transaction.receipt_id = transaction.receipt_id or values["receipt_id"]
        return value

transaction_one = Receipt(**data)

Upvotes: 0

Related Questions