Your First RESTful View in Drupal 8

In a continuation from my first post, An Introduction to RESTful Web Services in Drupal 8, I want to explore how Views interacts with REST in Drupal 8.

As many of you already know, the Views module was added to Drupal 8 Core. With RESTful Web Services also in Core, we now have all the tools we need to create highly customizable solutions out of the box.

In this blog post, I will show you how to create a view that returns a list of content in JSON via the REST API. Let’s get started!

First things first, we want to make sure both the REST and Serialization modules are enabled. Then we need to create some dummy content. To do this, grab the latest Drupal 8 development release of Devel module, and enable just the Devel generate submodule. Navigate to Configuration > Development > Generate content, and create a bunch of articles.

Now let’s create our view. We do not need to create a page or block, so uncheck those options to keep things simple.

After creating the view, you’ll notice we only have a Master display. For REST to work, we need to add a REST export display.

On the new REST export display, we need to set a path. This is the URL that will be used by clients to return the contents of the view. I’m using the following structure to keep things organized, but you can use anything you like.

REST export displays have a single output format, called Serializer It converts output into the format the client requests. In other words, when the client calls the URL we set above, they can specify the desired format output. If a format is not specified, Views returns JSON by default. There are 3 formats available: HAL, JSON, and XML. By default the client can request any of these formats, but if you open the Serializer settings dialog (found in the Format section of the view) you can specify which request formats are accepted.

REST export lets you to return either fields or entities. By setting our view to return entities, we'll get the entire serialized node object. And just like any view, selecting fields lets us pick the fields from the entity we wish to return. For the sake of simplicity here, I've opted to return the content title only.

Remember that we’re using Views, and we have access to its awesome features. We can set permissions to access the path, sort results by custom criteria, and limit the number of results. Views caching is still a work in progress, but once its functional we'll also be able to cache results like any other view. It’s brilliant!

Contextual filters work too. For example we could add the content author UID contextual filter, and clients could then append it to the end of the path (e.g., rest/views/articles/1) to filter results by a specific author.All that's left now is to give it a test run. Make sure to save the view, and then try accessing the URL directly in your browser. As we're not specifying a format, JSON is returned by default.

[{"title":"Eu Populus Wisi"},{"title":"Distineo Gemino Sit Sudo"},{"title":"Tation"},{"title":"Blandit"},{"title":"Consectetuer Lucidus Patria"},{"title":"Quae Valde"},{"title":"Ad Jumentum Quibus"},{"title":"Aliquam Jugis Saluto Ymo"},{"title":"Exputo Sagaciter Te"},{"title":"Bene Causa Neo Torqueo”}]

We can change aliases used for fields by opening the field settings dialog. This is useful if we want something user friendly and don't want to use default field labels.

I recommend using the Dev HTTP Client chrome extension for testing REST APIs. It will allow you to set the Accept header to return something other than JSON, and it formats the output to assist with debugging. It’s also worth noting that you can only use GET. Views won’t accept POST, PUT, PATCH, or DELETE operations.

I hope this was helpful for those of you who are excited about RESTful Web Services in Drupal 8 Core. Building a REST API for an application has always been tricky. Hopefully with the inclusion of REST and Views in Drupal Core, we’re one step closer to standardizing the process.

In a future blog post, I will dive into the OAuth Contrib module and how we can use it to improve the authentication security of our REST APIs. As always, feel free to leave comments and questions below. Thanks!

Related Topics: 

Comments

Hi,

I just wanted to see how the custom resources (especially the POST method) works in the Drupal 8 RESTful services.

Let's say i have a custom table 'xyz' and i just wanted to create a RESTful resource which will GET and POST data to these tables. Can you please show me some pointers in this?

You will have to create a new entity that defines the schema of this table. See this article for more: https://drupal.org/node/2192175

Yes, just as Alf said or if you want to stick with your custom table you would need to create a "resource plugin" like the rest module in core does for entities out of the box. There isn't much documentation out about this at the moment but there is a couple of slides on the subject by Lin Clark that might prove useful. http://lin-clark.com/d8-rest-slides/#36

Hello. Thank you for this great article ! But I have a strange problem : "/rest/views/articles/" works perfect but when I add the nid aflet I have an error ("rest/views/articles/1" : http://i.imgur.com/RaFLCWC.png). I have another error when I edit export_REST : http://i.imgur.com/qqre2oe.png. Last thing, when I try to access "/entity/node/1", I have a 404, is it normal ?
Thank you again for this nice article !

You might want to make sure you're on the lastest alpha version of Drupal 8. I've tested this article using Alpha 11 and it's working for me. To filter by Node ID using rest/views/articles/<nid> you will need to add the Content: Nid contextual filter to the view. Also, in a recent Drupal 8 core update the REST URIs for accessing nodes was changed so you should be able to access via /node/<nid>. If you haven't already, I'd recommend reading An Introduction to RESTful Web Services in Drupal 8.

Hey, thanks for this article.
I do have problems with the contextual filters though. As you wrote I have selected `/rest/thing/<nid>` as a path. But how can I use this variable in the Filter section? I tried 'Content: Nid (= <nid>)' but this is not working. (I get a 200 but an empty result set. If I set 'Content: Nid (= 1)' I get a result)

You don't need to add this to the Filters section. Contextual Filters are filters themselves. Just make sure you have "Content: Nid" set up to take its value from the URL path. Other than that you're free to set it up as you please. There is more information on contextual filters in the drupal.org documentation: https://drupal.org/node/1578558

Hello! Is there any way to get JSON from exposed filter result? Something like: user filters data in view, and I need to get the result of the filter in JSON?

Hi,

Thank you for the article. Do you know how I can get paging to work in restful view? By default, views show only 10 items at a time. When I try to go to 2nd page by supplying "?page=2" in url, it doesn't work.

Thanks.

Hi Seong,

Make sure the pager settings for your view are set to "Paged output" with either the full or mini pager. If you have either "Display a specified number of items" or "Display all items" as the selected pager settings the query parameter in the url won't work. If you're using either of "Paged output, full pager" or "Paged output, mini pager" you should be able to use the page query parameter to filter your results.

Cheers,

Blake

Hi Blake,

Thanks for the article. I have content working fine but can't figure out how to output the main menu as JSON to use with AngularJS. Any ideas? Menu items and views don't interact so I can't really use this method.

- Ash

Hi Ash,

Right now it looks like the easiest way to expose menu items would be to write a REST resource plugin module that supports menus. That's a great idea for a follow up blog post, and I'll add the idea to our queue. There's a bit of information about the overall architecture of the REST server in Drupal 8, as well as a pointer to see how these plugins are constructed in this video: https://drupalize.me/videos/exposing-your-api-drupal-8?p=2360

Hi

I've been playing around with the rest view, but I can't figure out how to output multiple taxonomy terms as an array.

Any pointers on how to do that?
Let's say you have a article end point (/api/articles/123) and there's a title, body and then tags field. I have then added tag A, B and C, how do I output them as an array along side the title and body fields?

Thanks this will be very useful as I will be creating a view like this using the calendar module to push out to an exchange server, any feedback on how to do this would be appreciated. Do we also have rest endpoints that can accept updates as well? https://www.freeenergymedia.com

Hi alexb,

I'd recommend checking out the documentation on Drupal.org about the REST server module included with core: https://www.drupal.org/documentation/modules/rest

It includes examples of GET, PATCH and POST requests.

Cheers,

Blake

hello.

Thank you for this article. It was very easy for me

I have links fields, and I do not know how I could post new content with that fields
{
"_links":{
"type":{
"href": "http://url/rest/type/node/"
}
},
"title": [{"value": "Title"}],
"body": [{"value": "Description"}],
"field_link_url": [{What do I write here?}],
"field_link_url2": [{What do I write here?}]
}

Could you help me?

Thank you very much

Hi Jesus,

The short answer is that you need to match the data structure Drupal is expecting. You can see an example of this in action when it comes to comments, and the body field, in the official drupal.org documentation here: https://www.drupal.org/documentation/modules/rest/javascript#comments. If you need help seeing what structure a particular field expects I'd recommend using the devel module on your local host. The devel tab on a particular node will show you Drupal's internal object structure.

Hopefully this helps get you on the right track. We'll be working on the long answer soon in a future blog post and series of tutorials.

I checked the html code with chrome tools, I checked than all you need is check the field name:
If the field name is "field_link_url[0][uri]" you will post the field with:
"field_link_url": [{"uri": "https://drupalize.me"}]

FInally the code would be:

{
"_links":{
"type":{
"href": "http://url/rest/type/node/"
}
},
"title": [{"value": "Title"}],
"body": [{"value": "Description"}],
"field_link_url": [{"uri": "https://drupalize.me", "title": "Drupalize"}],
"field_link_url2": [{"uri": "https://drupalize.me", "title": "Drupalize"}}]
}

Thank you for you help

Thanks for this article very helpful! I'm using D8 REST view to consume in an iOS app. I have paging working by passing in params like ?page=1, ?page=2 etc. However, I'm unsure how to determine when I'm on the last page through the API. Obviously, I can calculate this programmatically based on total # of entities and entities per page in the view, but is there a simple way the API exposes what the last page should be?

Thanks again!

Hi jjozwiak,

Off hand I'm not sure it's possible to add a count using the Views UI. I'd imagine you could add to the Views response before the render process.

If you'd like to give that a try, here are a list of the views hooks (https://api.drupal.org/api/drupal/core%21modules%21views%21views.api.php...). I'd probably start by trying out hook_views_pre_render() in a custom module.

Add new comment