Using python docx to create word documents

Python Docx

If you need to create a word doc on a server I recommend using the python package “docx”.

To install docx run

1
pip install python-docx

You can read through the official documentation here:

http://python-docx.readthedocs.io/en/latest/user/install.html

Styling your template

A useful thing to do is to style your template in microsoft word and then save the template and use it as your starting document.

eg

1
document = Document("document_path.docx", "path_to_template.docx"))

Some tricks I have learnt while using docx

First you create your document:

1
document = Document("path/doc.docx")

Then you add elements to your document using the following

  • add_paragraph
  • add_picture
  • add_page_break
  • add_heading
  • add_table
  • add_row

Examples

1
document.add_paragraph('Hello World'

Adding a table

1
2
3
4
table = document.add_table(rows=1, cols=5)
row = table.add_row().cells
index = 0
row[index].add_paragraph('Hello World')

XML

To view the xml of an element use element.xml

Eg

1
2
p = document.add_paragraph('Hello World')
p.xml

Advanced

I ran into a tricky part where I wanted to add content to the middle of an existing document with existing content.

I added this copy to the document “[BOOKMARK HERE]”

And then I used this code to search for that and then to add elements after that copy.

Add a paragraph after a paragraph, or a heading after a paragraph:

1
2
3
4
5
def addParagraphAfterParagraph(self, document, paragraph, bookmark = '[BOOKMARK HERE]'):
  for para in document.paragraphs:
    if para.text == bookmark:
      p = para._p
      p.addnext(paragraph._p)

To add a table after the copy I had to use something like this:

1
2
3
4
5
def addTableAfterParagraph(self, document, table, bookmark = '[BOOKMARK HERE]'):
  for para in document.paragraphs:
    if para.text == bookmark:
      p = para._p
      p.addnext(table._tbl)

To add an image after that copy I had to use something like this:

1
2
3
4
5
6
7
def addImageAfterParagraph(self, document, image_path, width, bookmark = '[IMAGE HERE]'):
  for para in document.paragraphs:
    if para.text == bookmark:
      p = para._p
      para.text = ''
      run = para.add_run()
      run.add_picture(image_path, width=width)

Also remember you have to run these in reverse because you’re adding it after an element, so it will place before the next element each time and immediately after the copy.

 

Scaffolding notes on django

Setup notes

Make sure the following is installed:

  • python
  • pip
  • virtualenv

Create a virtual environment:

1
eg: virtualenv env

Make sure django is installed:

1
pip install django

Scaffolding notes:

Create a project:

1
python-admin startproject [projectname]

Optionally create an app

1
2
3
cd [projectname]

python-admin startapp [appname]

Note! Make sure you cd into the project folder so that your app is in the same folder level as manage.py

Also remember to:

Add [appname] to INSTALLED_APPS in settings.py

Upgrading flask on a linux server, but getting version errors

Flask database throws errors when trying to upgrade and migrate

The following is a last resort solution for a problematic database, I have yet to find a cleaner solution for this problem.

Delete the existing version of alembic, and start from scratch

source ~/venvs/env.Vodacom-QuoteService/bin/activate

Clear the alembic table

sqlite3 [yourdbfile]
> delete * from alembic_version;

Remove the migrations folder

rm -r migrations/

Initialize the database

python manage.py db init

Upgrade and migrate the database

python manage.py db upgrade
python manage.py db migrate

Restart the service that is using the table.

Might need to rerun these three steps if the database is still not working

python manage.py db upgrade
python manage.py db migrate
(restart your service)

Struggling with selenium, splinter and phantomjs

If you’re trying to test with selenium and splinter, and getting failed tests in phantomjs but the tests work in chrome or firefox, try these settings:

Service arguments

browser = Browser(‘phantomjs’, service_args=[‘–ignore-ssl-errors=true’, ‘–ssl-protocol=any’, ‘–webdriver-loglevel=DEBUG’])

Maximize the window

browser .driver.maximize_window()

Or set your window size

browser .driver.set_window_size(1024, 1024)