Skip to content
Advertisement

How to write a django orm-like module?

I am trying to write a orm package which source data is json, First I created a Department class (I am trying to mimic django model)

class Department():
def __init__(self, data_dict):
    self.id = data_dict['id']
    self.organization_name = data_dict['organization_name']

def __str__(self):
    return f"<{self.__class__.__name__}(id={self.id})>"

Then I created Organization class as a search manager.

class Organization():
    data = [{
            "id": 1,
            "parent_id": 0,
            "organization_name": "President Office"
        },{
            "id": 2,
            "parent_id": 1,
            "organization_name": "Business Development Dept."
        },{
            "id": 3,
            "parent_id": 2,
            "organization_name": "Product Design Dept."
        }]
    def get(self,id):
        department_instance = None
        for department_dict in self.data:
            if department_dict['id'] == id:
                department_instance = Department(department_dict)
                break
    
        return department_instance

My expected result is:

org = Organization()
business_dev_dep = org.get(id=2) # <Department(id=2)>
business_dev_dep.parent_id # <Department(id=1)>

But I have no idea how to achieve it, can anybody help me?

Advertisement

Answer

If you want to access the parent object instance by class attribute you have to declare it in the Department class:

class Department(object):
    def __init__(self, data_dict):
        self.id = data_dict['id']
        self.parent_id = None
        self.organization_name = data_dict['organization_name']

    def __str__(self):
        return f"<{self.__class__.__name__}(id={self.id})>"

Then in your Organization class you can write a new method that searchs for the parent data and sets the attribute before returning it:

class Organization(object):
    data = [{
        "id": 1,
        "parent_id": 0,
        "organization_name": "President Office"
    }, {
        "id": 2,
        "parent_id": 1,
        "organization_name": "Business Development Dept."
    }, {
        "id": 3,
        "parent_id": 2,
        "organization_name": "Product Design Dept."
    }]

    def _get_parent(self, parent_id):
        # id == 0 means that the object doesn't have parent?
        if parent_id > 0 and parent_id in map(lambda x: x['parent_id'], self.data):
            parent_data = list(filter(lambda x: x['id'] == parent_id, self.data)).pop()
            return Department(parent_data)

    def get(self, id):
        department_instance = None
        for department_dict in self.data:
            if department_dict['id'] == id:
                department_instance = Department(department_dict)
                department_instance.parent_id = self._get_parent(department_dict['parent_id'])
                break
        return department_instance

Then you can access the parent attribute like you’re expecting:

org = Organization()
business_dev_dep = org.get(id=2) # <Department(id=2)>
business_dev_dep.parent_id

EDIT: That snippet only gets the first parent in the hierarchy. If you want to get all children from any node then you must rewrite the _get_parent function to be recursive:

class Organization(object):
    data = [{
        "id": 1,
        "parent_id": 0,
        "organization_name": "President Office"
    }, {
        "id": 2,
        "parent_id": 1,
        "organization_name": "Business Development Dept."
    }, {
        "id": 3,
        "parent_id": 2,
        "organization_name": "Product Design Dept."
    }]

def _get_parent(self, parent_id):
    # id == 0 means that the object doesn't have parent?
    if parent_id > 0 and parent_id in map(lambda x: x['parent_id'], self.data):
        parent_data = list(filter(lambda x: x['id'] == parent_id, self.data)).pop()
        parent = Department(parent_data)
        parent.parent_id = self._get_parent(parent_data['parent_id'])
        return parent

    def get(self, id):
        department_instance = None
        for department_dict in self.data:
            if department_dict['id'] == id:
                department_instance = Department(department_dict)
                department_instance.parent_id = self._get_parent(department_dict['parent_id'])
                break
        return department_instance

Now you can access all the parent objects from any node:

org = Organization()
business_dev_dep = org.get(id=3)
print(business_dev_dep.parent_id.parent_id)
<Department(id=1)>
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement