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?
Solution 1:
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)>