python - 如何编写类似 django orm 的模块?
问题描述
我正在尝试编写一个源数据为 json 的 orm 包,首先我创建了一个 Department 类(我试图模仿 django 模型)
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})>"
然后我创建了组织类作为搜索管理器。
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
我的预期结果是:
org = Organization()
business_dev_dep = org.get(id=2) # <Department(id=2)>
business_dev_dep.parent_id # <Department(id=1)>
但我不知道如何实现它,有人可以帮助我吗?
解决方案
如果你想通过类属性访问父对象实例,你必须在 Department 类中声明它:
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})>"
然后在您的Organization
类中,您可以编写一个新方法来搜索父数据并在返回之前设置属性:
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
然后你可以像你期望的那样访问父属性:
org = Organization()
business_dev_dep = org.get(id=2) # <Department(id=2)>
business_dev_dep.parent_id
编辑:该片段仅获得层次结构中的第一个父级。如果要从任何节点获取所有子节点,则必须将_get_parent
函数重写为递归:
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
现在您可以从任何节点访问所有父对象:
org = Organization()
business_dev_dep = org.get(id=3)
print(business_dev_dep.parent_id.parent_id)
<Department(id=1)>