[英]How to combine a QuerySet and a Dictionary in Django Template?
[英]How to convert a django queryset to a dictionary for use as a template context
我正在重新創建Django中的寶石庫存狀態報告,該報告最初是在Microsoft Access中構建的。 該報告的組織如下:
以下是模型的相關部分:
class Deal(models.Model):
deal_name = models.TextField()
class Stone(models.Model):
stoneid = models.TextField(verbose_name='StoneID', unique=True)
dealid = models.ForeignKey(Deal, on_delete=models.PROTECT)
ct_in = models.DecimalField(verbose_name='Carats', max_digits=7, decimal_places=3)
cost_purchase = models.DecimalField(verbose_name='Purchase Cost', max_digits=14, decimal_places=2, null=True, blank=True)
我通過兩個查詢得到數據 - 一個用於細節線,另一個用於小計。 以下是查詢:
def dump_stone(request):
query = Stone.objects.filter(Q(dealid_id__deal_name='ABC') | \
Q(dealid_id__deal_name='DEF') | \
Q(dealid_id__deal_name='GHI')).select_related().order_by('dealid_id__deal_name', 'inventory_status', 'stoneid')
totals = Stone.objects.values('dealid', 'inventory_status').annotate(sum_by_deal=Sum('cost_purchase'), sum_ct_in_by_deal=Sum('ct_in'))
通過交易按狀態打印庫存明細表的模板是:
{% block content %}
REPORT:
</br>
{% regroup context by dealid as deal_list %}
{% for dealid in deal_list %}
{{dealid.grouper}}
{% regroup dealid.list by inventory_status as stone_list%}
{% for inventory_status in stone_list %}
{{inventory_status.grouper}}
<table>
<thead>
<tr>
<th>StoneID</th>
<th>Ct</th>
<th>Cost</th>
</tr>
</thead>
<tbody>
{% for stone in inventory_status.list %}
<tr>
<td>{{ stone.stoneid }}</td>
<td>{{ stone.ct_in|floatformat:2 }}</td>
<td>{{ stone.cost_purchase|prepend_dollars }}</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
{% endfor %}
{% endblock content %}
總計查詢生成以下輸出:
{'dealid': 1, 'inventory_status': 'HistoricFYI', 'sum_by_deal': Decimal('1287750'), 'sum_ct_in_by_deal': Decimal('15.1500000000000')}
{'dealid': 1, 'inventory_status': 'Sold', 'sum_by_deal': Decimal('209138.7100000'), 'sum_ct_in_by_deal': Decimal('327.810000000000')}
{'dealid': 2, 'inventory_status': 'Sold', 'sum_by_deal': Decimal('338726.99000000'), 'sum_ct_in_by_deal': Decimal('56.2000000000000')}
{'dealid': 3, 'inventory_status': 'Inventory', 'sum_by_deal': Decimal('296754.5900000'), 'sum_ct_in_by_deal': Decimal('294.970000000000')}
{'dealid': 3, 'inventory_status': 'Memo In', 'sum_by_deal': Decimal('192948.340000000'), 'sum_ct_in_by_deal': Decimal('9.47000000000000')}
{'dealid': 3, 'inventory_status': 'Sold', 'sum_by_deal': Decimal('154384.57000000'), 'sum_ct_in_by_deal': Decimal('88.1200000000000')}
{'dealid': 5, 'inventory_status': 'Inventory', 'sum_by_deal': Decimal('187000'), 'sum_ct_in_by_deal': Decimal('26.75')}
{'dealid': 5, 'inventory_status': 'Sold', 'sum_by_deal': Decimal('20000'), 'sum_ct_in_by_deal': Decimal('2')}
{'dealid': 5, 'inventory_status': 'Test', 'sum_by_deal': Decimal('13700'), 'sum_ct_in_by_deal': Decimal('19')}
我想要做的是將總計查詢轉換為字典字典,以便我可以通過交易,按狀態訪問單個小計,並使用標記將它們插入模板中的正確位置(不會很難) -coded如圖所示,但我將繼續下一步):
{{deal_dict.1.Sold.sum_by_deal}}
我正在嘗試生成一個如下所示的字典:
{ 1:
{
‘HistoricFYI’:{’sum_by_deal': Decimal('1287750'), 'sum_ct_in_by_deal': Decimal('15.1500000000000’)},
'Sold:{'sum_by_deal': Decimal('209138.7100000'), 'sum_ct_in_by_deal': Decimal('327.810000000000’)}
},
2:
{
’Sold’:{‘sum_by_deal': Decimal('338726.99000000'), 'sum_ct_in_by_deal': Decimal('56.2000000000000’)},
},
3:
{
'Inventory’:{‘sum_by_deal': Decimal('296754.5900000'), 'sum_ct_in_by_deal': Decimal('294.970000000000’)},
'Memo In’:{‘sum_by_deal': Decimal('192948.340000000'), 'sum_ct_in_by_deal': Decimal('9.47000000000000’)},
'Sold’: {‘sum_by_deal': Decimal('154384.57000000'), 'sum_ct_in_by_deal': Decimal('88.1200000000000')}
},
5: {
'Inventory’:{‘sum_by_deal': Decimal('187000'), 'sum_ct_in_by_deal': Decimal('26.75’)},
'Sold’: {‘sum_by_deal': Decimal('20000'), 'sum_ct_in_by_deal': Decimal(‘2’)},
'Test’: {‘sum_by_deal': Decimal('13700'), 'sum_ct_in_by_deal': Decimal('19')}
}
}
我已經嘗試了一些東西來獲取總計查詢集並使其成為嵌套字典:
deal_dict = {}
status_dict = {}
numbers_dict = {}
for things in totals:
print(things)
numbers_dict['sum_by_deal']=things['sum_by_deal']
numbers_dict['sum_ct_in_by_deal']=things['sum_ct_in_by_deal']
status_dict[things['inventory_status']]=dict(numbers_dict)
deal_dict[things['dealid']]=dict(status_dict)
上述代碼的問題在於,每筆交易的嵌套字典包括先前交易的狀態,除非交易本身具有覆蓋先前數據的該狀態的自己的數據。 換句話說,對於交易2,例如我得到
{ 2:
{
‘HistoricFYI’:{’sum_by_deal': Decimal('1287750'), 'sum_ct_in_by_deal': Decimal('15.1500000000000’)},
'Sold:{'sum_by_deal': Decimal('338726.99000000'), 'sum_ct_in_by_deal': Decimal('56.2000000000000’)}
},
即使它沒有自己的任何“HistoricFYI”數據,因為字典仍包含交易1數據。
我也嘗試過這樣清理字典
status_dict.clear()
在每個循環結束時,但我最后只收到每個交易(銷售或測試)按字母順序排列的最后狀態字典。
我也試過了
deal_dict = {}
for things in totals:
deal_dict.update({things['dealid']:{things['inventory_status']:{'sum_by_deal': things['sum_by_deal'], 'sum_ct_in_by_deal': things['sum_ct_in_by_deal']}}})
但這只是字典中每個交易的最后狀態,就像我嘗試了clear()方法一樣。
我無法弄清楚如何調整這個 - > Django模板中的Totals / Subtotals或者這個 - > Django:如何處理平面查詢集到嵌套字典?
我怎樣才能生成這個字典詞典,以便我可以在模板中插入小計,或者以某種方式將小計插入到正確的位置? 我非常感謝任何幫助!
這似乎實現了你想要的嵌套字典:
def regroup_inventory(totals_qset):
for dealid, row_group in groupby(totals_qset, key=itemgetter('dealid')):
yield dealid, {
row['inventory_status']: {
key: val
for key, val in row.items()
if key not in ('dealid', 'inventory_status')
}
for row in row_group
}
注意:這是一個生成器,所以你需要像在dict.items()
一樣迭代它,或者在結果上調用dict()
。 試試你的例子,我得到:
> from decimal import Decimal
> from pprint import pprint
> foo = [
{'dealid': 1, 'inventory_status': 'HistoricFYI', 'sum_by_deal': Decimal('1287750'), 'sum_ct_in_by_deal': Decimal('15.1500000000000')},
{'dealid': 1, 'inventory_status': 'Sold', 'sum_by_deal': Decimal('209138.7100000'), 'sum_ct_in_by_deal': Decimal('327.810000000000')},
{'dealid': 2, 'inventory_status': 'Sold', 'sum_by_deal': Decimal('338726.99000000'), 'sum_ct_in_by_deal': Decimal('56.2000000000000')},
{'dealid': 3, 'inventory_status': 'Inventory', 'sum_by_deal': Decimal('296754.5900000'), 'sum_ct_in_by_deal': Decimal('294.970000000000')},
{'dealid': 3, 'inventory_status': 'Memo In', 'sum_by_deal': Decimal('192948.340000000'), 'sum_ct_in_by_deal': Decimal('9.47000000000000')},
{'dealid': 3, 'inventory_status': 'Sold', 'sum_by_deal': Decimal('154384.57000000'), 'sum_ct_in_by_deal': Decimal('88.1200000000000')},
{'dealid': 5, 'inventory_status': 'Inventory', 'sum_by_deal': Decimal('187000'), 'sum_ct_in_by_deal': Decimal('26.75')},
{'dealid': 5, 'inventory_status': 'Sold', 'sum_by_deal': Decimal('20000'), 'sum_ct_in_by_deal': Decimal('2')},
{'dealid': 5, 'inventory_status': 'Test', 'sum_by_deal': Decimal('13700'), 'sum_ct_in_by_deal': Decimal('19')},
]
> pprint(dict(regroup_inventory(foo)))
{1: {'HistoricFYI': {'sum_by_deal': Decimal('1287750'),
'sum_ct_in_by_deal': Decimal('15.1500000000000')},
'Sold': {'sum_by_deal': Decimal('209138.7100000'),
'sum_ct_in_by_deal': Decimal('327.810000000000')}},
2: {'Sold': {'sum_by_deal': Decimal('338726.99000000'),
'sum_ct_in_by_deal': Decimal('56.2000000000000')}},
3: {'Inventory': {'sum_by_deal': Decimal('296754.5900000'),
'sum_ct_in_by_deal': Decimal('294.970000000000')},
'Memo In': {'sum_by_deal': Decimal('192948.340000000'),
'sum_ct_in_by_deal': Decimal('9.47000000000000')},
'Sold': {'sum_by_deal': Decimal('154384.57000000'),
'sum_ct_in_by_deal': Decimal('88.1200000000000')}},
5: {'Inventory': {'sum_by_deal': Decimal('187000'),
'sum_ct_in_by_deal': Decimal('26.75')},
'Sold': {'sum_by_deal': Decimal('20000'),
'sum_ct_in_by_deal': Decimal('2')},
'Test': {'sum_by_deal': Decimal('13700'),
'sum_ct_in_by_deal': Decimal('19')}}}
我沒有測試過這一點,但我想你想你的deal_dict
是一個defaultdict
。 然后從thing
彈出dealid和inventory_status,並使用它們將deal_dict填充為嵌套字典。
from collections import defaultdict
deal_dict = defaultdict(dict)
for thing in totals:
dealid = thing.pop('dealid')
status = thing.pop('inventory_status')
deal_dict[dealid][status] = dict(thing)
編輯:我應該添加一個警告,這將改變totals
,如果你再去其他地方使用它將會有問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.