我目前正在计划一个django应用程序,它不仅允许用户构建与模型相关的自定义表(例如,用户可以创建一个与"员工"模型相关的琐碎的自定义"停车位"表,而无需编辑models.py),还可以使用这些自定义表构建自定义报告。我唯一能想到的方法是建立一个在JSONField中存储自定义表数据的模型(我使用Postgres作为后端,所以这实际上很好),然后建立一个报告模型,允许用户构建和保存"类似SQL"的查询,为他们的自定义报告返回连接的数据集。
我已经学会了如何存储自定义表并在我的应用程序中使用它们,我甚至对如何将伪外键上的多个JSON对象合并到自定义报告中有一个松散的概念,但我只创建了一对一连接。
使用下面的脚本,如果我的任何dict在一个外键上有多个记录,则只使用最后一个记录。有人知道我如何实现多个python字典的一对多连接吗?
如果我有这三个数据集:
employees = [{"id": 1, "user_id": 303, "name": "Mike"},
{"id": 2, "user_id": 304, "name": "James"},
{"id": 3, "user_id": 305, "name": "David"},]
roles = [{"id": 1, "user_id": 303, "role": "Manager"},
{"id": 2, "user_id": 304, "role": "Assistant"},
{"id": 3, "user_id": 305, "role": "Assistant"},]
absences = [{"id": 1, "user_id": 303, "date": "2015-03-01"},
{"id": 2, "user_id": 303, "date": "2015-03-02"},
{"id": 3, "user_id": 303, "date": "2015-03-03"},
{"id": 4, "user_id": 304, "date": "2015-03-15"},
{"id": 5, "user_id": 305, "date": "2015-03-19"},]
我希望直接加入的结果是:
[{'date': '2015-03-01', 'role': 'Manager', 'user_id': 303, 'id': 1, 'name': 'Mike'},
{'date': '2015-03-02', 'role': 'Manager', 'user_id': 303, 'id': 1, 'name': 'Mike'},
{'date': '2015-03-03', 'role': 'Manager', 'user_id': 303, 'id': 1, 'name': 'Mike'},
{'date': '2015-03-15', 'role': 'Assistant', 'user_id': 304, 'id': 2, 'name': 'James'},
{'date': '2015-03-19', 'role': 'Assistant', 'user_id': 305, 'id': 3, 'name': 'David'}]
但由于我的脚本首先循环通过FROM字典(在本例中是员工),所以我所能得到的就是:
[{'date': '2015-03-03', 'role': 'Manager', 'user_id': 303, 'id': 1, 'name': 'Mike'},
{'date': '2015-03-15', 'role': 'Assistant', 'user_id': 304, 'id': 2, 'name': 'James'},
{'date': '2015-03-19', 'role': 'Assistant', 'user_id': 305, 'id': 3, 'name': 'David'}]
下面是我的代码的基础:
def joiner(from_table, joins):
report_data = []
for row in from_table:
new_row = row
for table in joins:
table_dict = table["table"]
table_fk = table["fk"]
for tdr in table_dict:
if tdr[table_fk] == row[table_fk]:
for field in table["fields"]:
new_row[field] = tdr[field]
report_data = from_table
return report_data
join_tables = [{"table": roles, "fk": "user_id", "fields": ["role"]},
{"table": absences, "fk": "user_id", "fields": ["date"]},
]
joiner(employees, join_tables)
我能想到的最简单的解决方案是从"缺席"dict作为from_table而不是employees开始,但这是一个多对一的加入,这对我来说是非常有限的。
此外,如果有人对构建用户创建的数据模式有更好的想法,可以使用django将其合并到自定义报告中,我会洗耳恭听。我能想到的唯一其他解决方案是完全绕过django模型,只使用直接SQL创建、更新和查询所有自定义表。
只要在调用合并时将最长的字典列表放在第一位(可以很容易地修改),这里就是一个粗略的解决方案
def merge_lists(listdict1, listdict2,listdict3, joinkey):
mergedlist=listdict1
for i in range(len(listdict1)):
for j in range(len(listdict2)):
if (listdict1[i][joinkey]==listdict2[j][joinkey]):
for keys in listdict2[j].keys():
mergedlist[i][keys]=listdict2[j][keys]
for k in range(len(listdict3)):
if listdict1[i][joinkey]==listdict3[k][joinkey]:
for keys in listdict3[k].keys():
mergedlist[i][keys]=listdict3[k][keys]
return mergedlist
merge_lists(absences, employees, roles, "user_id")
[
{
"date":"2015-03-01",
"id":1,
"name":"Mike",
"role":"Manager",
"user_id":303
},
{
"date":"2015-03-02",
"id":1,
"name":"Mike",
"role":"Manager",
"user_id":303
},
{
"date":"2015-03-03",
"id":1,
"name":"Mike",
"role":"Manager",
"user_id":303
},
{
"date":"2015-03-15",
"id":2,
"name":"James",
"role":"Assistant",
"user_id":304
},
{
"date":"2015-03-19",
"id":3,
"name":"David",
"role":"Assistant",
"user_id":305
}
]