Skip to content

Import and export

Buhle Ntshalintshali edited this page Feb 6, 2024 · 5 revisions

Importing and Exporting Content

Fields

The exporter will export content with the following fields, and the importer expects these fields to be present:

Field name Field description
structure This shows where in the nested structure this content is found. The importer doesn't use this information, it infers it through the parent field, but it is helpful to identify where this content fits in the nested structure when viewing the document
message This is a number representing which message in the content page this row is for. It is used when a content page has multiple messages, which get spread across multiple rows
page_id The ID of this content page in the database. This isn't used in the import, the slug field is used instead as a unique identifier for a page
slug The slug of the page. This is used to uniquely identify the page. During an import, if a page with the same slug is found, it is overwritten instead of a new page being added
parent The title of the parent of this page
web_title The title of the web portion of this page
web_subtitle The subtitle of the web portion of this page
web_body The body of the web portion of this page
whatsapp_title The title of the whatsapp portion of this page
whatsapp_body The body of the whatsapp portion of this page. If there are multiple whatsapp messages for a page, they are placed in separate rows
whatsapp_template_name If this page is a whatsapp template, the name of that template
whatsapp_template_category The category of WhatsApp template
example_values If this is a whatsapp template with variables, example values for those variables. Comma separated list
variation_title If this message has any whatsapp variations, then this is the identifier for which user profiles this variation is appropriate for. It has the format of the type and value separated by a colon, with multiple of these separated by commas. eg gender: male, relationship: single
variation_body The body of this whatsapp variation message. If there are multiple variation messages, they are added as multiple rows
sms_title The SMS title
sms_body The SMS body. If there are multiple messages, they are put as additional rows
ussd_title The USSD title
ussd_body The USSD body. If there are multiple messages, they are put as additional rows
messenger_title The facebook messenger title
messenger_body The facebook messenger body. If there are multiple messages, they are put as additional rows
viber_title The viber title
viber_body The viber body. If there are multiple messages, they are put as additional rows
translation_tag The translation key. This is used to link translations together. Two pages with the same translation key are considered translations of each other
tags A comma separated list of tags
quick_replies A comma separated list of quick replies
triggers A comma separated list of triggers
locale The language that this content is in
next_prompt The button text to see the next whatsapp message in this content page
buttons A JSON serialisation of the whatsapp buttons for this message. It is an array of objects, each objects having the keys "type", which can be "next_prompt" or "go_to_page", and "title", which is the text for the button. Additionally, the "go_to_page" button type has a "slug" key, which is the slug of the page that it refers to. eg. [{"type": "next_prompt", "title": "Next"}, {"type": "go_to_page", "title": "See more", "slug": "more-info"}]
image_link The link for the first image across the content types. Not imported
doc_link The link for the whatsapp document. Not imported
media_link The link for the whatsapp media. Not imported
related_pages A comma separated list of slugs for pages that are related to this one
list_items This is a whatsapp template with list messages they are comma separated list

Import content

To import content, in the admin UI select ContentPages from the left panel, and select the Import button. You will be presented with a form with the following fields:

  • File: The file to upload, that contains the data to be imported.
  • File type: Whether this is an XLSX or CSV file.
  • Purge: Whether all content should be deleted before importing, ensuring that the content in the import file is the only content present after the import is complete.
  • Locale: Which locale to import from the uploaded file.

After clicking "Upload", you will be presented with a progress bar that shows the progress of the import. After the import is complete, if it is successful, you will get a success message. If it is not, you will get a generic error message. Someone will have to investigate the application logs to see what the issue is with the uploaded file.

Content can be imported in XLSX or CSV format. The importer has the option to purge all content, this will delete all ContentPage and ContentPageIndex objects from the database and replace them with the rows of the content sheet that is uploaded. This will ensure that only the content in the import file is present after the import, which allows you to delete rows from the content sheet, and have that change be reflected after import.

The excel document and the CSV will have header rows that look like

structure message page_id slug parent web_title web_subtitle web_body whatsapp_title whatsapp_body whatsapp_template_name whatsapp_template_category variation_title variation_body list_items sms_title sms_body ussd_title ussd_body messenger_title messenger_body viber_title viber_body translation_tag tags quick_replies triggers locale next_prompt buttons image_link doc_link media_link related_pages

The importer iterates over each row of the sheet. If the row has a web_title, but does not have a parent, web_body, whatsapp_body, messenger_body, viber_body, sms_body or ussd_body the page created will be a ContentPageIndex, and it will be added under the HomePage with the specified locale.

If there is a web_title, then the page is created as a ContentPage.

If there is no web_title, but there is a variation_body, then it is created as a variation message to the last whatsapp message for the ContentPage specified by the row's slug.

If there is no web_title and no variation_body, but there are either whatsapp_body, messenger_body, viber_body, sms_body or ussd_body then it is added as a message to the ContentPage specified by the row's slug.

All values are stripped of leading and trailing whitespace before being imported.

Images, documents, and media are not currently imported.

The page_id row is ignored on import. The slug is used to find the existing content page when importing. This is done to ensure that content can be reliably imported across different instances of ContentRepo, that may have different page IDs for the same piece of content. As such, it is enforced that slugs are unique.

Export ContentPage

To perform an export, in the Admin UI, select ContentPages. You will see a button on the top right for Download XLSX. If you want CSV format instead, click the dropdown arrow next to this button, and select Download CSV.

The export creates a CSV or XLSX file in the same format the importer expects.

The XLSX has additional styling, layout, and frozen panels added to it, but otherwise is identical to the CSV format.

The export works by going through all the locales and getting the home page for each locale. Then it does a breadth-first search on each home page, exporting each page as a row as it goes through. For content pages with multiple messages, each additional message is added as an extra row to the export.

The export logic can be found in home/export_content_pages.py. ExportRow is a class that represents one row in the export. ContentExporter is responsible for reading from the database, and creating a resulting list of ExportRows. ExportWriter receives a list of ExportRows, and is responsible for writing it in either CSV or XLSX format.

Clone this wiki locally