Generate Document from Python Dicts and Lists
Leave feedback
Overview
One of the most common scenarios in document assembly is generating reports from your application’s own data. GroupDocs.Assembly for Python via .NET binds Python dicts and lists directly to templates: each dict reaches the template as an object whose members are the dict’s keys, so the template text is the same as for .NET objects.
Here are the steps to generate documents from your own data:
Describe each record as a dict whose keys are the member names the template reads
Fill the dict (or a list of dicts) with data
Create a template document with expression tags referencing those members
Use DocumentAssembler to assemble the template with your data
Save the assembled document
Note
A dict’s values may be str, int, float, decimal.Decimal, bool, datetime/date, None, and nested dicts and lists. The value’s type decides what the template can do with it: a date format such as "yyyy-MM-dd" needs a datetime or date, and a currency format needs a number. Anything else (a function, an instance of your own class) raises TypeError before the engine is called.
Describe a Customer
Start by deciding which keys the template reads. A customer record looks like this:
fromdatetimeimportdatetimefromdecimalimportDecimalcustomer={"Name":"Quayside Bistro","Email":"orders@quaysidebistro.example","Address":"3 Harbour Steps, Port Ellery","RegistrationDate":datetime(2015,1,14),"Balance":Decimal("1250.75"),}
Generate Document from Single Object
Generate a document from a single dict:
fromdatetimeimportdatetimefromdecimalimportDecimalfromgroupdocs.assemblyimportDataSourceInfo,DocumentAssembler# Create and populate the recordcustomer={"Name":"Quayside Bistro","Email":"orders@quaysidebistro.example","Address":"3 Harbour Steps, Port Ellery","RegistrationDate":datetime(2015,1,14),"Balance":Decimal("1250.75"),}# Assemble documentassembler=DocumentAssembler()assembler.assemble_document("customer-profile.docx","customer-profile-report.docx",DataSourceInfo(customer,"customer"))print("Document generated from custom object successfully.")
You can also generate documents from a list of dicts:
fromdecimalimportDecimalfromgroupdocs.assemblyimportDataSourceInfo,DocumentAssembler# Create a list of recordscustomers=[{"Name":"Quayside Bistro","Email":"orders@quaysidebistro.example","Balance":Decimal("1000")},{"Name":"Lantern Street Café","Email":"orders@lanternstreetcafe.example","Balance":Decimal("2500")},{"Name":"Saltmarsh Deli","Email":"orders@saltmarshdeli.example","Balance":Decimal("750")},]assembler=DocumentAssembler()assembler.assemble_document("customer-balances.docx","customer-balances-report.docx",DataSourceInfo(customers,"customers"))print("Document generated from collection successfully.")
A .NET object can expose a method such as GetTotal() for the template to call. A dict has no methods, and a function stored in a dict is rejected with TypeError (“function cannot be part of a data source given as a dict”). Calculate the value in the template expression instead, or store the result under its own key in Python:
fromdecimalimportDecimalfromgroupdocs.assemblyimportDataSourceInfo,DocumentAssemblerproduct={"Name":"Lighthouse Espresso beans","Price":Decimal("21.75"),"Quantity":2,}assembler=DocumentAssembler()assembler.assemble_document("product-line.docx","product-line-report.docx",DataSourceInfo(product,"product"))print("Document generated with a calculated total successfully.")
The following sample file is used in this example: product-line.docx
Keep calculations in templates simple. When a value needs your application’s logic, compute it in Python and pass it as one more key ("Total": price * quantity).
Using Instances of Your Own Classes
An instance of a Python class cannot be passed as it is: the call raises TypeError (“Object of type Customer is not JSON serializable”). Pass its attributes as a dict with vars(). This converts one level only, so a nested instance needs its own vars():
fromdecimalimportDecimalfromgroupdocs.assemblyimportDataSourceInfo,DocumentAssemblerclassCustomer(object):def__init__(self,name,email,balance):self.Name=nameself.Email=emailself.Balance=balancecustomers=[Customer("Quayside Bistro","orders@quaysidebistro.example",Decimal("1000")),Customer("Pier Nine Kitchen","orders@piernine.example",Decimal("320.50")),]# vars() turns each instance into the dict of its attributesassembler=DocumentAssembler()assembler.assemble_document("customer-balances.docx","customer-balances-from-classes.docx",DataSourceInfo([vars(customer)forcustomerincustomers],"customers"))print("Document generated from class instances successfully.")
To learn more about working with complex data hierarchies, collections, LINQ queries over your data, and performance optimization, please refer to the advanced usage section.
More resources
GitHub Examples
You may easily run the code above and see the feature in action in our GitHub examples: