Table of Contents
Motivation
If you had less menial manual work you could sit at the beach and relax more often 🙂
So regarding my pain points I figured out that publishing articles to my blog takes a huge amount of time too.
In order to publish an article I need to:
- Log in into the WordPress backend
- Create a new post in the WordPress backend
- Insert the markdown text for the article into the post (I write my articles in markdown and use github for versioning)
- Convert the markdown format into HTML by pressing the enter key on every tag (sic!) (so that ## becomes h2)
- Upload all media / images
- Insert images into the post
- Select the featured image
- Write some SEO relevant metadata
- Publish the post
Why not “Automate the boring stuff” here as well? In this part I will show you the first part of publishing a post.
Prerequisites
For uploading we use the requests module. So let’s install it via:
pip install requests
Application Password
As another prerequisites we need an application password:
- Log in to your WordPress site with an admin user account
- Navigate to Users > Profile.
- Scroll down to the “Application Passwords” heading.
- Enter an application name
- Click “Add New Application Password”
- Store the generated password in a secure place
Uploading Posts
data = {
'title': 'Example wordpress post',
'status': 'draft',
'slug': 'example-wordpress-post',
'author': 1,
'content': '# H1 heading \n ## h2 heading'
}
This is the minimal data you have to provide to be able to create a post via API.
The author has to be an integer. You can find the users’ ids via https://<your_wordpress_site>
Authentication
For authentication you need a header:
WORDPRESS_CREDENTIALS = USER_NAME + ":" + APPLICATION_PASSWORD
WORDPRESS_TOKEN = base64.b64encode(WORDPRESS_CREDENTIALS.encode())
WORDPRESS_HEADER = {'Authorization': 'Basic ' + WORDPRESS_TOKEN.decode('utf-8')}
USER_NAME has to be a real user with admin rights not the application password name (It got me confused)
Posting the Post
We use the REST API v2 which is located at:
WORDPRESS_API = "https://<your_wordpress_site>/wp-json/wp/v2"
The endpoint for uploading posts is
API_ENDPOINT = WORDPRESS_API + "/posts"
Now we have all information to finally post the post
def upload_post(data):
response = requests.post(API_ENDPOINT, json=data, headers=WORDPRESS_HEADER)
return response
Little helpers
Creating slugs
Normally the slug for a post is the title just with lowercase and hyphen instead of spaces
(That’s what the editor in the wp backend would normally do automatically)
So let’s do this programmatically as well:
def make_slug_from_title(title):
slug = title.lower().replace(" ", "-")
return slug
Converting from markdown to HTML
With the markdown package you can convert your article before uploading
pip install Markdown
html_text = markdown(article_content, output_format="html")
Just one line of additional code. I love Python!
Reading and Converting a markdown file
To create the data for the upload in one go I wrote a convenience function:
def get_article_data(folder):
base_dir = '../content'
article = os.path.join(base_dir, folder, folder + ".md")
with open(article, "r") as f:
title = f.readline().replace("#", "").strip()
article_content = f.read()
html_text = markdown(article_content, output_format="html")
slug = make_slug_from_title(title)
data = {
'title': title,
'status': 'draft',
'slug': slug,
'author': 1,
'content': html_text,
}
return data
Putting it together
With these helpers you can condense it into
data = get_article_data(folder)
upload_post(data)