Using the AppReport client on Web2py Apps - simpleservices/app_report-python GitHub Wiki
Requirements to install the app_report package
- To install the app_report package we need the pip tool,
If you are Ubuntu, don't worry, ubuntu ships with pip, however if you are on Windows and haven't installed pip yet, please follow this instructions How to install pip on Windows before installing the app_report package.
Installing the app_report package
-
Having pip installed, create a file called requirements.txt inside your app directory, and add 'app_report' (without the quotes) to it and save.
-
On ubuntu, open the terminal and install the requirements with:
cd path/to/web2py/applications/your_app
pip install -r requirements.txt --upgrade
- On Windows, open the terminal and install the requirements with:
cd c:\path\to\web2py\applications\your_app
c:\Python27\Scripts\pip.exe install -r requirements.txt --upgrade
How to use the AppReport client in a web2py app
You can use the AppReport client in your application following just few steps:
Configuring the client
Once you had installed the app_report package, in a model (eg models/0.py) put the following code:
# If you are on Windows and using the web2py.exe executable to start the server,
# you may need to uncomment the lines below, to import packages instaled via pip:
#
# (You may change the Python location based on your Python version and install location).
#
#import sys
#sys.path.append('c:\Python27\Lib\site-packages')
import app_report
from app_report.helpers.reports import jasper_report
from app_report.helpers.serializers import rows_to_xml
# Replace this configuration with the name and credentials of your own app ,
# you can see it at the "App settings" page on [AppReport site](http://reports.simpleservic.es/).
app_report.AppReport.configure({
'app_name': 'your-app-name',
'access_key': 'your-app-access-key',
'secret_key': 'your-app-secret-key'
})
This code do two important things:
- First it import the app_report module and some helpers, that will be used after in a controller to generate the pdf reports.
- And after it configure the client with the credentials of your own app, previously created at the AppReport site.
Generating PDF reports
-
Assuming that you have the following model for products:
db.define_table('products', Field('name'), Field('quantity', 'integer'), Field('price', 'double'), Field('disabled', 'boolean', default=False) )
And a controller to create products, like this:
def create(): form = crud.create(db.products) products = db(db.products.id > 0).select() return dict(form = form, products = products)
1 - Create a controller called products_report.py, and put the following code:
def datasource(): query = db(db.products.id > 0) response.headers['Content-Type'] = 'application/xml' return rows_to_xml(rows=query.select(), fields=db.products.fields, parent_tag='products', child_tag='product')
This code will implement the datasouce action to your controller.
-
This action is responsible to generate the XML that will be used as a datasource of your report, it means that this XML contains the data that you want to show on the report.
-
Note that we are using the helper rows_to_xml to transform a set of rows in a XML.
-
You can see the XML generated on your browser, eg: http://localhost:8000/shop/products_report/datasource.
2 - Design your report on the i-report tool
- Now that you have an url to access the XML datasource, you are able to connect an i-report datasource to this url, so you can design your report on i-report.
3 - Upload your report template to the AppReport site
After drawn your report on i-report you must upload the generated .jrml file to the AppReport site.
4 - Include actions to generate the HTML form and PDF report
After you had uploaded the report to the AppReport site, you can include the following actions to the products_report.py controller:
def form(): form = FORM( TABLE( INPUT(_type='submit', _value='Print') ), _action='pdf', _method='post', _target='_blank' ) return dict(form=form) def pdf(): report = jasper_report(template_name='your-template-name', data=str(datasource()), xpath_expression='products/product', response=response, content_disposition='inline') return report
-
This code will add two important actions to your controller:
-
form
- This action is responsible to generate the HTML form, that the users of your application will fill to print the report, note that it example, only have a submit button, but we will add more inputs, so the users will be able to filter the informations that they want to print.
- Note that we are saying to the browser to send the requests to an action called 'pdf' and open the report in a blank (new) page.
-
pdf
- This action is responsible to receive the requests sent by the HTML form and generate the PDF report.
- Note that we are using the helper jasper_report to generate the reports, passing a few important arguments to it method:
- template_name, this is the name of the report (that you previously had uploaded to the AppReport site), that you want to print.
- data, this is the string of the XML that you are sending as datasource of the report, note that the XML is generated by the datasource action.
- xpath_expression, this is the xpath expression that will be applied to the XML datasource sent, when printing the report.
This is a optional argument, by default it value is set to /template_name(plural)/template_name(singular), it means that for a template_name 'products', the default value will be /products/product. - response, here we are sending the web2py response object, it is util, because the helper will set for us the headers with the appropriate content type to pdf, it will also set the content disposition to attachment by default.
- content_disposition, this argument just change the default content disposition to inline, it means that the report will be rendered in the page instead of asking if the user want to save the PDF file.
5 - Try it!
Come on don't be afraid, just access the form on your browser and see what happens :P, try http://localhost:8000/shop/products_report/form
--
Adding some filters
Ok, your reports are being generated like a charm, but what do if you want to allow the users to filter the products that will be displayed at the report?
Don't worry bro, you can do this more easier that you think, we just need to include some inputs on the HTML form and some logic on the datasource action of your controller.
In this example we will allow the users to filter the products by quantity, price (in a range) and by status (disabled, enabled or all):
-
So let's put some logic to the datasource action, change it to:
def datasource(): query = db(db.products.id > 0) # dynamic query if request.vars.quantity: query = query(db.products.quantity == request.vars.quantity) if request.vars.initial_price: query = query(db.products.price >= request.vars.initial_price) if request.vars.final_price: query = query(db.products.price <= request.vars.final_price) if request.vars.disabled in ('True', 'False'): query = query(db.products.disabled == request.vars.disabled) response.headers['Content-Type'] = 'application/xml' return rows_to_xml(rows=query.select(), fields=db.products.fields, parent_tag='products', child_tag='product')
Note that we included one "if clause" for each filter, and we are getting the value of each filter accessing request.vars, so we can easily send the filter value just including HTML inputs to the HTML form.
But, before change the form, try to access the datasource view, sending different vars so you will can see the filters in action, eg:
- http://127.0.0.1:8000/shop/products_report/datasource?disabled=False
- http://127.0.0.1:8000/shop/products_report/datasource?disabled=True
- http://127.0.0.1:8000/shop/products_report/datasource?quantity=10
- http://127.0.0.1:8000/shop/products_report/datasource?quantity=10&disabled=False
- http://127.0.0.1:8000/shop/products_report/datasource?initial_price=100
-
Now that we are able to change the HTML form, change the form action to:
def form(): form = FORM( TABLE( [LABEL('Quantity'), INPUT(_name='quantity')], [LABEL('Price between'), INPUT(_name='initial_price'), 'and', INPUT(_name='final_price')], [LABEL('Disabled'), SELECT('All', True, False, _name='disabled')], INPUT(_type='submit', _value='Print') ), _action='pdf', _method='post', _target='_blank' ) return dict(form=form)
Note that we included one HTML element for each filter, now just access the form url http://127.0.0.1:8000/shop/products_report/form and be happy :)
Need help?
If you have any question about AppReport feel free to contact us at reports.simpleservic.es/support