Reputation: 20581
I'm trying to create a custom page on my domain that has the url 'http://example.com/test/slug', however the slug does not seem to support slashes (the slug '/test/slug' turns into '/testslug'). Is it possible using the rest api to create a page on a custom url? Also, I populate the 'meta' dictionary, however the page created does not contain a meta 'description' tag in the header. How can I correctly create custom meta tags?
import requests
url = 'http://example.com/wp-json/wp/v2/pages'
data = {'content': '<h2>test content</h2>',
'meta': {'description': 'this is a test meta field'},
'slug': 'test/slug',
'status': 'publish',
'title': 'test title'}
resp = requests.post(url, json=data, auth=('user','pass'), headers={'Content-Type':'application/json'})
Upvotes: 4
Views: 4502
Reputation: 17297
First, make sure your Permalinks settings is "Post Name".
This can be configured under http://<yoursite.com>/wp-admin/options-permalink.php
I have studied "Custom Permalinks" plugin code to understand how to answer this question, it saves a metadata called "custom_permalink" and does heavy INNER JOINS to make WordPress core work with "fake" sub-slugs.
I came up with a different solution. The trick here is to create a fake parent page to serve as a base URL for children pages. I have written it in PHP, since I don't know Python.
<?php
require_once('helpers.php');
define('API_URL', 'http://temp.localhost');
# Let's get all pages in an array
$pages = curlGet(API_URL.'/wp-json/wp/v2/pages');
# Your usual $args
$args = array(
'title' => 'API TEST',
'status' => 'draft',
'content' => 'content',
'slug' => 'some/thing'
);
# We intercept it here, before sending to WordPress
$args = maybe_add_parent($args);
$response = curlPost( API_URL.'/wp-json/wp/v2/pages/', $args );
/**
* Receives an $args array that would be sent to WordPress API and checks if we need to add a parent page
*/
function maybe_add_parent(array $args) {
if (array_key_exists('slug', $args)) {
# Has parent?
if (strpos($args['slug'], '/') !== false) {
$parent = explode('/', $args['slug']);
# For simplicity sake let's do it parent/chidren slugs only
if (count($parent) !== 2) {
die('This script can only run parent/children slugs');
}
$slug = array_pop($parent);
# Here, we will check the parent to see if it exists.
$parent_id = slug_exists($parent[0]);
if ($parent_id === false) {
# If it does not, it will create it and return it's ID
$parent_id = create_parent($parent[0]);
}
# Add parent ID to $args.
$args['parent'] = $parent_id;
# Rename the slug
$args['slug'] = $slug;
}
}
return $args;
}
/**
* Checks if a given slug exists in $pages
*/
function slug_exists(string $slug) {
global $pages;
foreach ($pages as $page) {
# Checks if a "Parent" page with this slug exists
if ($page['slug'] == $slug && $page['parent'] == 0) {
return true;
}
}
return false;
}
/**
* Creates a parent page
*/
function create_parent(string $slug) {
$args = array(
'title' => $slug,
'status' => 'draft',
'content' => '',
'slug' => $slug
);
$response = json_decode(curlPost( API_URL.'/wp-json/wp/v2/pages/', $args ));
return $response->id;
}
The script does the following:
parent/child
parent
page existsparent
key and return $argsparent/child
It works:
Upvotes: 2
Reputation: 15620
the slug does not seem to support slashes (the slug '/test/slug' turns into '/testslug').
Yes, because whether you use the REST API or the admin UI for creating Pages, the slug is limited to alphanumeric characters, plus dashes (-
) and underscores (_
). See https://developer.wordpress.org/rest-api/reference/pages/#schema-slug.
You can remove the limitation by adding remove_filter( 'sanitize_title', 'sanitize_title_with_dashes', 10, 3 );
to the theme's functions.php
file (or a custom plugin); however, visiting the page (URL) would by default throw a 404 (not found) error. There are ways to fix that, but in short, you should not remove the filter.
Is it possible using the rest api to create a page on a custom url?
No it's not, not by default.
However, if you want http://example.com/test/slug
to serve/show a Page/Post/etc. be it created via the REST API or not, then you can use custom URL rewrite rules, e.g. via add_rewrite_rule()
.
the page created does not contain a meta 'description' tag in the header. How can I correctly create custom meta tags?
You need to register the meta key, which in your case is description
.
See
And you can register it using the register_meta()
function in wp-includes/meta.php.
Example for your description
meta:
<?php
// The object type. For custom post types, this is 'post';
// for custom comment types, this is 'comment'. For user meta,
// this is 'user'.
$object_type = 'post'; // 'post' even for Pages
$args1 = array( // Validate and sanitize the meta value.
// Note: currently (4.7) one of 'string', 'boolean', 'integer',
// 'number' must be used as 'type'. The default is 'string'.
'type' => 'string',
// Shown in the schema for the meta key.
'description' => 'A meta key associated with a string meta value.',
// Return a single value of the type.
'single' => true,
// Show in the WP REST API response. Default: false.
'show_in_rest' => true,
);
register_meta( $object_type, 'description', $args1 );
To quickly test if the meta description
was successfully registered and that it's being available from the REST API, perform a GET
request to http://example.com/wp-json/wp/v2/pages/<id>
where <id>
is the Page ID.
Upvotes: 2
Reputation: 5041
To get the URL structure you want, the most straightforward way is to create a child page that references an already existing page as it's parent.
To amend your example above:
import requests
url = 'http://example.com/wp-json/wp/v2/pages'
parent_page = 43 # assuming that page with URL '/test' has id of 42
data = {'content': '<h2>test content</h2>',
'meta': {'description': 'this is a test meta field'},
'slug': 'slug',
'status': 'publish',
'title': 'test title'
'parent': parent_page} # <--
resp = requests.post(url, json=data, auth=('user','pass'), headers={'Content-Type':'application/json'})
Would give you a new page at example.com/test/slug
Reference to arguments for "Create a Page", (POST /wp/v2/pages
) on WordPress rest API Handbook: https://developer.wordpress.org/rest-api/reference/pages/#create-a-page
Upvotes: 1