Working with Posts¶
python-wordpress-xmlrpc supports all registered WordPress post types.
Behind the scenes in WordPress, all post types are based on a single “post” database table, and all of the functionality is exposed through the posts methods in the XML-RPC API.
For consistency, the same approach is adopted by python-wordpress-xmlrpc.
Note
Posts will be sent as drafts by default. If you want to publish a post, set post.post_status = ‘publish’.
Normal Posts¶
First, let’s see how to retrieve normal WordPress posts:
from wordpress_xmlrpc import Client
from wordpress_xmlrpc.methods import posts
client = Client(...)
posts = client.call(posts.GetPosts())
# posts == [WordPressPost, WordPressPost, ...]
And here’s how to create and edit a new post:
from wordpress_xmlrpc import WordPressPost
post = WordPressPost()
post.title = 'My post'
post.content = 'This is a wonderful blog post about XML-RPC.'
post.id = client.call(posts.NewPost(post))
# whoops, I forgot to publish it!
post.post_status = 'publish'
client.call(posts.EditPost(post.id, post))
Pages¶
Out of the box, WordPress supports a post type called “page” for static non-blog pages on a WordPress site. Let’s see how to do the same actions for pages:
from wordpress_xmlrpc import WordPressPage
pages = client.call(posts.GetPosts({'post_type': 'page'}, results_class=WordPressPage))
# pages == [WordPressPage, WordPressPage, ...]
Note two important differences:
- The
filter
parameter’spost_type
option is used to limit the query to objects of the desired post type.- The constructor was passd a
results_class
keyword argument that told it what class to use to interpret the response values.
And here’s how to create and edit a page:
page = WordPressPage()
page.title = 'About Me'
page.content = 'I am an aspiring WordPress and Python developer.'
page.post_status = 'publish'
page.id = client.call(posts.NewPost(page))
# no longer aspiring
page.content = 'I am a WordPress and Python developer.'
client.call(posts.EditPost(page.id, page))
Custom Post Types¶
While the pages example used its own results_class
, that was a unique situation because pages are special in WordPress and have fields directly in the posts table.
Most custom post types instead use post custom fields to store their additional information, and custom fields are already exposed on WordPressPost
.
For this example, let’s assume that your plugin or theme has added an acme_product
custom post type to WordPress:
# first, let's find some products
products = client.call(posts.GetPosts({'post_type': 'acme_product', 'number': 100}))
# calculate the average price of these 100 widgets
sum = 0
for product in products:
# note: product is a WordPressPost object
for custom_field in product.custom_fields:
if custom_field['key'] == 'price':
sum = sum + custom_field['value']
break
average = sum / len(products)
# now let's create a new product
widget = WordPressPost()
widget.post_type = 'acme_product'
widget.title = 'Widget'
widget.content = 'This is the widget's description.'
widget.custom_fields = []
widget.custom_fields.append({
'key': 'price',
'value': 2
})
widget.id = client.call(posts.NewPost(widget))
Advanced Querying¶
By default, wordpress_xmlrpc.methods.posts.GetPosts
returns 10 posts in reverse-chronological order (based on their publish date). However, using the filter
parameter, posts can be queried in other ways.
Result Paging¶
If you want to iterate through all posts in a WordPress blog, a server-friendly technique is to use result paging using the number
and offset
options:
# get pages in batches of 20
offset = 0
increment = 20
while True:
posts = client.call(posts.GetPosts({'number': increment, 'offset': offset}))
if len(posts) == 0:
break # no more posts returned
for post in posts:
do_something(post)
offset = offset + increment
Ordering¶
If you don’t want posts sorted by post_date
, then you can use orderby
and order
options to change that behavior.
For example, in sync scenarios you might want to look for posts by modification date instead of publish date:
recently_modified = client.call(posts.GetPosts({'orderby': 'post_modified', 'number': 100}))
Or if you want your ACME products sorted alphabetically:
products = client.call(posts.GetPosts({'post_type': 'acme_product', 'orderby': 'title', 'order': 'ASC'}))
Post Status¶
Another common scenario is that you only want published posts:
published_posts = client.call(posts.GetPosts({'post_status': 'publish'}))
Or only draft posts:
draft_posts = client.call(posts.GetPosts({'post_status': 'draft'}))
You can find the set of valid post_status
by using the wordpress_xmlrpc.methods.posts.GetPostStatusList
method.