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.

Image

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

Image

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.

Image

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.

Image

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.

Image

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.

Image

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.

Image

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!

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?

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.

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

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.ph…). I'd probably start by trying out hook_views_pre_render() in a custom module.

The 2nd page is ?page=1 not ?page=2, because the counting starts with 0!

Hi Asit,

To the best of my knowledge the sort criteria can't be changed dynamically via the query string. If you need to add support for something like this your best best is to either switch to use something more robust (like JSON API) or to write a custom Views plugin to use the query string to manipulate the results before they're returned.

Cheers,

Blake

I've not actually tried this so YMMV. However, I believe this should work the same as for example authenticating a POST request using the REST server. https://www.drupal.org/docs/8/core/modules/rest/3-post-for-creating-con… This would allow you to authenticate the request, and assuming the user who makes the request is authorized to view the requested resource I think it should work.

That example shows using Basic HTTP Authentication. But other methods like Session (send the Cookie with the request) or OAuth (send the bearer token header) should work as well.

Let us know how it goes.

I like to create a view like this
I don't know how to add the collection name in Views, Is this possible?

{
"vehicles"
[ { "Make":"Toyota",
"Model":"A"
},
{ "Make":"Simca",
"Model":"1100"
}
]
}

Hi Rosso,

I'm not entirely sure what you mean by collection name, but it sounds to me like you might be able to accomplish what you're trying to do by using field aliases (as mentioned above).

If that doesn't give you enough flexibility, you can use most other views theming techniques to manipulate the output of these views too.

I have created a Restapi through view and want to use his path to display his data in a formatted view via custom module. please suggest anyone.

Great article! How can I add total count and pager information in Rest Export view as we add in the normal view form Header.
I am using facet serializer due to having multiple facets. I want to add total count & pager information in this serializer.
Note :- I have used this module drupal.org/project/pager_serializer/ which gives the total count in API but it gives an option to use either pager serializer or facet serializer. I have to use both at a time. Any solution for the toal count?

Add new comment

Filtered HTML

  • Web page addresses and email addresses turn into links automatically.
  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <code class> <ul type> <ol start type> <li> <dl> <dt> <dd><h3 id> <p>
  • Lines and paragraphs break automatically.

About us

Drupalize.Me is the best resource for learning Drupal online. We have an extensive library covering multiple versions of Drupal and we are the most accurate and up-to-date Drupal resource. Learn more