Update table in Confluence through Python

Question:

I created a Confluence page some time ago, where there is one table. Periodically I need to add additional row and to put some text there. I would like to automate it. Besides, in the last column I need to upload some files.

I wrote a code that can get (download) table from Confluence page. But I am thinking, how to write new information in new row in that table in Confluence through Python. From research that I have carried out I decided that I need to update that table in Python (as dataframe) that I have got from Confluence. After that upload new table into Confluence. Is this idea correct?

I suppose that modified table (dataframe) in Python I need to put as

conf.update_page(page_id, page_content), 

However, I get an error like "Object of type DataFrame is not JSON serializable". Could you help me, please? I do not know, how to solve it. Perhaps, something is incorrect.

As I have written before, I need to attach some documents to the last column of the table. I completely do not understand how to do it. There are some functions that can attach something to Confluence, but I need to attach files in the last column and the last (created) row. Do I need to do it in dataframe (modified table) in Python or should I do it in Confluence after uploading modified table there? If so, I do not understand, how to explain to Python to put it exactly in the last column as I only download table to Python from Confluence. Moreover, when

Below there is a code, by which I got table from Confluence.

     from atlassian import Confluence
     import pandas as pd

     conf_site = 'https://confluence.company.com/'
     conf_user = "login"
     conf_pass = "password"
     page_id = 0000000000

     conf = Confluence(url=conf_site, username=conf_user, password=conf_pass)
     page = conf.get_page_by_id(page_id, expand='body.view')
     page_content = page['body']['view']['value']

     table = pd.read_html(page_content)
     table = table[0]

This table was open in Python as dataframe and I created new row in it and put essential information. However, I do not comprehend, how to add it to Confluence page. I got an error written above.

Asked By: Anastasia

||

Answers:

I’ve done a similar project, except I was creating a Conf page instead. I found the easiest way to do it is to just create the html code yourself

This plugin lets you view the source code for a Confluence Page. It’s an XML based language which makes it quite easy to use in python. I suggest reading up on this as it was quite useful I found:

https://marketplace.atlassian.com/apps/1210722/confluence-source-editor?tab=overview&hosting=server

This is how I was attaching files and then getting the link.
I then use BeautifulSoup4 to find the spot in the code to put the link (Although I created a template for myself)

confluence.attach_file(spur_path, name=None, content_type=None, page_id=pid, title=None, space="spacename", comment="Automatically added")

#Adding plots to HTML code
conf_spur_plot = "http://wiki:8090/download/attachments/" + pid + "/" + spur_filename
soup.find("a", {"class": "spurplot"})["href"] = conf_spur_plot

Quick example of getting and updating a confluence page

#login to confluence
confluence = Confluence(
    url='http://confluence',
    username='user',
    password='pass')

#get page id of the page
pid = confluence.get_page_id(space, title)

#get page from page id
conf_page = confluence.get_page_by_id( expand='body.storage', page_id=pid)

#Check contents
contents = conf_page["body"]["storage"]["value"]

#Stringify the contents
#You can turn this into a beautifulsoup4 object and can then use all the bs4 #methods which can help a lot
conf_string = str(contents)

html_example = "<p>This is an example<p>"

#Add the html example to the contents
conf_string += html_example

#Update the page with the new body
confluence.update_page(
    page_id=pid,
    title="Example",
    body=conf_string)

This below code is just an example of BS4 usage with confluence.
This code creates a BS4 object with the contents from confluence, parsed as XML
Then it finds the 3rd (index = 2) table and gets all the rows except the header row.

conf_html = BeautifulSoup(contents, 'xml')
child_soup = conf_html.find_all("table")[2]
all_rows = child_soup.find_all("tr")[1:]

Edit: As an example:

<ac:structured-macro ac_name="html" ac:schema-version="1">
  <ac:plain-text-body>
    <![CDATA[{0}]]>
  </ac:plain-text-body>
</ac:structured-macro>

The above code is the confluence xml for the html macro. For my program I simply do html_macro.format(example_data). And then I can add that to my confluence page with update_page(), and the html macro with my example data is rendered.

<ac:layout>
<ac:layout-section ac_type="two_equal">
    <ac:layout-cell>
      <table>
        <tbody>
          <tr>
            <th style="text-align: left;">Description</th>
            <th>Test Report</th>
          </tr>

          <tr>
            <th style="text-align: left;"PN</th>
            <td>
                <p>
                  <a class="link-here" href="">PN2</a>
              </p>
            </td>
          </tr>
        </tbody>
      </table>
    </ac:layout-cell>

Another example of a table in confluence. After creating the Soup object:
soup.find("a", {"class": "link-here"})["href"] = link_to_plot
This line uses BS4’s function to find an a tag with class: "link-here" and then change it’s href value.
I manually had to put in classes and ID’s in my template xml file to do this. Classes and tags should save on confluence, so if you add them once, it should work every next time.

Hope this helps

Answered By: mrblue6