Aaron Beaudoin
Aaron Beaudoin

Reputation: 577

How do I generate an Odoo PDF report from Python?

I'd like to generate a PDF containing all stock.report_picking reports for all deliveries for a given sale order, merged into one file. I've already done something similar for shipping labels where each label was saved as an ir.attachment record.

But in this case, the stock.report_picking report doesn't appear to be saved anywhere as far as I can tell. It appears to be regenerated on the fly whenever the user opens the "Print" menu and clicks on the report action (or if I go to /report/pdf/stock.report_picking/<id>).

So how would I generate the report in Python such that I can get the binary PDF data for the report (similar to the datas field on an attachment record) so I can then pass a list of report datas to the odoo.tools.pdf.merge_pdf function? I can then get my final result and do whatever I want with it (send it back via an HTTP response, save it in an attachment record, or whatever).

I know I could just make an HTTP request to /report/pdf/stock.report_picking/<id> for each record I want a report for, and then grab the binary data from the response. But that just seems like the wrong way to achieve something I should be able to do right inside of Python. I can't find anything in the official documentation concerning how to achieve this.

So then, back to the title: How do I generate an Odoo PDF report from Python?

Upvotes: 1

Views: 3567

Answers (1)

Aaron Beaudoin
Aaron Beaudoin

Reputation: 577

I figured it out! The answer is in odoo/addons/web/controllers/main.py starting on line 1964. This is the source code for the /report/<converter>/<reportname>/<docids> route briefly mentioned in my question and at the very end of the official documentation for reports here.

First of all, it turn out if you want a PDF with multiple records for a report combined into one file the /report/pdf/stock.report_picking/<id> URL can also have the <id> parameter be a comma separated list of report IDs. That way, you don't even need to get each report separately and merge them with odoo.tools.pdf.merge_pdf. Why this isn't documented is a mystery to me.

But, furthermore, the source code for the route also shows exactly what you can call to just generate the report from your own code! It's pretty simple:

report_name = "stock.report_picking"
report = env["ir.actions.report"]._get_report_from_name(report_name)

# `report_output` is a tuple where `report_output[0]` is the binary output
# and `report_output[1]` is the "converter" (in this case, "pdf").
report_output = report.render_qweb_pdf([<id>, ...])

You can then just take report_output[0] and do whatever you want with it. For example:

with open("report.pdf", "wb") as pdf_file:
    pdf_file.write(report_output[0])

Odoo is awesome, but the docs skip over so much of what the platform can do. You better get good at searching and reading source code if you want to write modules!

Upvotes: 1

Related Questions