Ghost API & Python 3.x, #2
In this second part of the tutorial we want to read the content of our Ghost sites.
First we want to access the list of all members of a site. We create the method getMembers():
def getMembers(self):
members = {}
url = self.site['url']+'ghost/api/v3/admin/members/'
result = requests.get(url, headers=self.headers)
if result.ok:
members = json.loads(result.content)['members']
for i in members:
if i['name'] == None: i['name'] = ''
return members
We use the endpoint /members/ . This endpoint is not yet in the documentation. Call the method (members = ga.getMembers()) and you get a list of dicts with keys for each dict like id, email, name.
Now we would like to read a single post. We can access a post either by its id or by its slug. We create the 2 methods getPostBySlug(postSlug) and getPostById(postId) .
def getPostBySlug(self,slug):
url = self.site['url'] + 'ghost/api/v3/admin/posts/slug/'+slug+'/'
params = {'formats':'html,mobiledoc'}
result = requests.get(url, params=params, headers=self.headers)
if result.ok: post = json.loads(result.text)['posts'][0] # post = dict with keys: slug,id,uuid,title etc.
else: post = json.loads(result.text) # post = dict with key 'errors'
return post
def getPostById(self, id):
url = self.site['url'] + 'ghost/api/v3/admin/posts/' + id + '/'
params = {'formats':'html,mobiledoc'}
result = requests.get(url, params=params, headers=self.headers)
if result.ok: post = json.loads(result.text)['posts'][0] # post = dict with keys: slug,id,uuid,title etc.
else: post = json.loads(result.text) # post = dict with key 'errors'
return post
The slug of a post is the rightmost part of the post-url. It can be found under the settings tab of a post (see Post URL). The id can be found in the database. It's not visible under the settings tab of the post. We have added the parameter 'formats' to the request object. By default only the mobiledoc version of the content is returned. To get the html version too, we have to use the 'formats' parameter (don't use a space between 'html' and 'mobiledoc').
We call these methods:
if __name__ == '__main__':
ga = GhostAdmin('somedomain1')
post = ga.getPostBySlug('someSlug') # e.g. 'my-new-post'
post = ga.getPostById('someId') # e.g. '5f91a94181840b0eae0ccd5c' = post['id'] from getPostBySlug()
In both cases the result is a dict with keys slug, id, uuid, title etc. A description of the return object is here.
Now we want to read 1 to many posts using a filter. Examples of filters are: 1. {'filter': 'featured:true'} (Fetch posts which are marked 'featured') 2. {filter: "tag:photo, featured:true, image:-null"} (Fetch posts which have either a tag of 'photo', are marked 'featured' or have an image). We don't go into the details of the query language but start right away with an example. You can find detailed information here and many examples here.
We create the method getPostsByFilter(filter):
def getPostsByFilter(self,filter):
url = self.site['url'] + 'ghost/api/v3/admin/posts/'
params = filter
params['formats'] = 'html,mobiledoc'
result = requests.get(url, params=params, headers=self.headers)
if result.ok:
posts = json.loads(result.text)['posts'] # posts = list with dicts with keys: slug,id,uuid,title etc.
if len(posts) == 0: posts = [{'empty': 'list'}]
else: posts = [json.loads(result.text)] # posts = list with 1 element of dict with key 'errors'
return posts
The filter is added to the get request (params=filter). We want to find all featured posts:
if __name__ == '__main__':
ga = GhostAdmin('somedomain1')
posts = ga.getPostsByFilter({'filter': 'featured:true'})
We get a list of dicts, each dict with keys slug, id, uuid, title etc.
To retrieve a list of all posts, we create the method getAllPosts(). It sets no limit ('limit': 'all') to the number of returned posts (by default, only 15 records are returned at once) and you can add a filter (all posts except ...).
def getAllPosts(self):
url = self.site['url'] + 'ghost/api/v3/admin/posts/'
params = {'formats': 'html,mobiledoc', 'limit': 'all', 'filter': 'slug: -tags'}
result = requests.get(url, params=params, headers=self.headers)
posts = json.loads(result.text)['posts']
return posts
There is no endpoint like /postbytitle/. Therefore we create a method getPostByTitle(title). This method uses getAllPosts() and iterates over the returned list to find all matching posts. It returns a list of dicts.
def getPostByTitle(self,title):
allPosts = self.getAllPosts()
posts = []
for i in allPosts:
if i['title'] == title:
posts.append(i)
return posts
In part 3 we will create and update posts.