Headless Wagtail CMS: Exposing Custom Page Fields to the v2 API

This video is from Wagtail CMS 2023 .

Headless Wagtail CMS: Exposing Custom Page Fields to the v2 API
0:10:23
Published November 29, 2023
4,302 views

In the last lesson we enabled Wagtails v2 API but we didn't have access to our custom fields.. yet! In this lesson we'll learn how, in just 4 lines of code, we can make a custom Wagtail Page field show up in our API. And it only gets easier from here.

How to enable Wagtails v2 API (Headless CMS): https://www.youtube.com/watch?v=VT9-qdI96rE

Tutorial: https://learnwagtail.com/tutorials/headless-cms-exposing-custom-page-fields-v2-api/

Learn Wagtail from scratch with the official Wagtail for Beginners Course
https://learnwagtail.com/wagtail-for-beginners/

Git Commit: https://github.com/CodingForEverybody/learn-wagtail/commit/9ce96e6cbb047224e0fe6cf39e155687b0dfe274 #Wagtail #Django #Python

Summary

Wagtail’s v2 API does not expose custom fields on a page model by default, but adding them is straightforward: import `APIField` and declare an `api_fields` list on the page class. The example exposes a banner title, rich-text subtitle, image, and page-linked call to action, showing how the API returns text, image metadata and URLs, and linked page details. The speaker also demonstrates using the `fields` query parameter to exclude or request fields, reducing unnecessary response data and potentially improving performance.

Key takeaways

  • Custom Wagtail page-model fields must be explicitly added to the v2 API with `APIField`.
  • An `api_fields` list can expose text, rich text, images, and foreign-key page relationships.
  • Image and linked-page fields return useful metadata and detail URLs for headless front ends.
  • The `fields` query parameter can exclude unwanted fields or request all available fields.
  • Adding each additional custom field requires only one more `APIField` entry.

Summarised automatically from the transcript.

Transcript

1,947 words · auto-generated Show

Automatically transcribed, so expect mistakes in names and technical terms.

0:00

Hello and welcome back to another lesson on learning Wagtail. In the previous lesson, we learned all about installing and enabling the Wagtail V2 API so that we can create some sort of headless CMS for React or View. or Angular or some sort of front-end framework to consume. Now at the end of the video, we got to a place where uh we were looking at items or uh a particular page and so we were looking at actually page three which is our homepage And we noticed that we actually had missing information in here. We didn't have everything that we needed. And if we open up our models. py We can see that in our homepage, so I'm in home slash models. Oh there it is. My site homodels. py and I'm in the home page class

0:48

We actually have a banner title, subtitle, image, and a banner CTA, which is a foreign key to another page. Now, none of this stuff actually shows up in our API. And the reason for that is because we have to explicitly tell it to show up in here. Now, if you're a little bit concerned that this might get really difficult. I'm gonna tell you it's not. It is really easy. And in fact, in I think it's four lines of code, we can add one custom field in here. With five lines of code, we can add two, and so on and so on. It's really, really easy. And in fact, I'm going to demonstrate that for you right now. So we're going to customize our homepage just a little bit, and we need to import well this is our Wagtail API. So let's go in here. Wagtail, Wagtail, Wagtail.

1:34

Let's go to the very top here. From Wagtail. api import API field. So that's step one. And step two is really easy. I like to keep these together, so if there's a content panel, yeah I scrolled right by it. There's one more that we have have to add in here now. It's called API fields. API fields. And this is going to be a list. And we're going to give it an API field with which one do we want in here? Let's put our banner title. Bruce Banner, he is the title that we need. So I'm gonna save that. I already have my server running and when I refresh Hello Banner title is in there. Look at that. Isn't that nice? Okay, so that was one, two, three.

2:21

Four lines of code. Now we want to add one more, so let's add our banner subtitle Okay, I'm just gonna copy and paste that. We also have a banner image in here, so let's go and add that banner image. And we have a banner CTA. And these are all if I remember correctly. different types of data. So our banner CTA is a foreign key. Banner image, actually that's also going to be a foreign key, but that's going to be to an image. Subtitle is going to be a rich text field, and our banner title is going to be a regular char field. So save that, refresh our page, and our banner subtitle, look at that, has parsed HTML in it already. Our banner image gives us an image ID, gives us uh metadata.

3:10

So what type of what type of image is this? Uh is this using wagtailimages. image or is it using a custom image class? This will give you a detail URL and a download URL. So you can simply stick these into your application at any point in time and someone can view the original image And it also gives you a title. Now if you wanted more details about that, you could simply click on this link in here, but because I'm missing the port and I don't want to change that at the moment. I'm simply going to paste this into my URL and it's going to be localhost port 8000 slash API slash V2 slash images slash 2. And so this gives us exactly what we're looking for: images, uh, very similar data.

3:55

We notice that this comes in a single object, it's not in some sort of list anymore, and it gives us a width and a height So that's the default width and height that comes from our default image. Also gives us a list of tags. So you get a little more information when you go to the detail view. And our banner CTA is null. So let's actually go and change that. Let's see what happens if we. Simply go and change that to a page. And I gotta make that smaller. Home page. Where is the CTA? There it is. Choose a page and let's choose any other page. Let's go to the blog. Sure. Okay, that's been saved and oh look at that our banner CTA. It's a foreign key

4:40

to an ID that has an ID of five It has metadata. It tells us what type of page it is. It gives us a detail URL. So if we wanted to see this URL, we would simply go to pages slash 5, which we can see at the end here. And now we have detailed information about our blog page And in fact, this one even gives us our parent information because we're not looking at the homepage, we're looking at an inner page. This one has a parent ID, homepage, so this is good for structuring your single page application. And it gives you detail U URL, uh HTML URL, title, and all that good stuff. So that's all we really need to do to enable additional fields. So now this is really cool, and if we go back to our listing page, we are going to see that in page 3, this is our homepage

5:32

We don't have the additional information that we need. So what if we needed to get all of the blog listing pages, but we needed that additional information? How do we get that from the listing page? Because as of right now, we have a problem. The problem is we are getting all of our pages, which is a total of eight, but we don't have any additional information. We just have the basic stuff. So this is good enough for creating links, but it's not good enough for creating any sort of visuals in your application. And in order to go and get any additional data, we actually have to click this link. I'm gonna append that port there. And then we can get all the extra information that we need. But on your homepage detail view, which is what we're looking at here, a home page has no parent.

6:17

Uh title, banner, title, banner, subtitle, image, all that good stuff. What if we didn't want all of this information? Right now this is this is using 13 queries. Let's refresh. 13 queries consistently in a total of three milliseconds. What if we said, you know what, we actually don't need the first published at, uh, we don't need a parent, we don't need an SEO title. We could we could actually change this in our URL. This is really, really nice actually. This is something that is relatively new in the world of web. I've been around for a long time. And this is a fantastic, fantastic idea So you type question mark fields is equal to and then you put a negative sign in front of the field that you don't want. So for instance, let's get rid of our SEO title

7:04

right there. So SEO title. There's no more SEO title. Let's get rid of the first published at. So all I'm going to do is put a comma, negative sign, first published at. Get rid of that one And so we can see that's not in there anymore. Let's also get rid of parent. Parent. There's no more parent in there. So you can see that this is actually reducing the number of queries. By telling the API to only give you data that you actually need, you can speed up your application by quite a bit. Now in this instance The uh processing time for my number of queries doesn't actually change, it's still around three milliseconds. That's two milliseconds.

7:50

A little bit better What if we wanted no fields? We could do this. And in fact, I'm going to make a video about this right after this one. We're going to go into how we can customize our views and what the API s gives us back. But just as a quick little overview, get riding getting rid of all views is simply an underscore. And if we wanted all fields This will give us all of our available fields. So there's a lot more to this. We can do a lot of stuff with our URL. All we have to do is change our URL and it will give us the data that we are telling it to give us. It automatically parses it for us, it does all the heavy lifting and all of a sudden we can do more front end work than we have to do back

8:35

end work. And in my opinion, this is why Wagtail CMS is a leader in headless CMS. I know WordPress and Drupal and all those other ones, they all have this already, but they don't make it this easy. Because if you said, hey Caleb, can you turn uh can you turn my Wagtail website into a headless CMS and uh only return certain fields? I could tell you, yeah, I can do that for you right now. It will take me six minutes. It's not going to take me an hour. It's not going to take me a day. Customizing it is super super easy. The data structure is already there. All we have to do is expose it to the API. Nice and simple. So I got a little bit distracted here, and what I'm going to do is I'm going to split what I was talking about into a different video. But the core of this video was all about making

9:21

additional fields that we have written in our custom Wagtail page, we want those to be exposed in our API. And that's exactly what we did. And remember it only took us four lines of code and then for every additional field was just one more line This has been nice and simple for us to uh actually just to put it to use immediately. It only took us a couple of minutes realistically. Now I'm going to leave this code in a git commit in the description down below If you have more questions about the API field, which we are going to tackle in future lessons, but if you have more questions right now, you can always go to docs. wagtail. io. They cover a lot of goodies in there. My name is Caleb Tallin, I'm the voice behind the video. You can also find more videos like this at learnwagtail. com. If you like this video, if you found it helpful

10:07

Feel free to click share, subscribe, or even leave a comment down below. And if you're interested in seeing the rest of the videos in this playlist, you can always click That square to the top right and that will bring you to all the other Learn Wagtail videos on YouTube. Thanks for watching and I'll see you in the next video

Questions this talk answers

How do I expose custom Wagtail page fields in the v2 API?

Import `APIField` from `wagtail.api` and add an `api_fields` list to the page model, with one `APIField` entry for each custom field. The first field takes about four lines of code, and each additional field adds another line.

Discussed at 1:34

What does the Wagtail v2 API return for custom image and page fields?

An image field returns an image ID, metadata, title, detail URL, and download URL; its detail endpoint also provides dimensions and tags. A page foreign key returns the page ID, type, metadata, detail URL, title, and—when applicable—parent information.

Discussed at 3:10

How can I choose which fields the Wagtail API returns?

Add a `fields` query parameter to the API URL and prefix fields you want to omit with a minus sign, such as `?fields=-seo_title,-first_published_at,-parent`. You can also use an underscore to request no fields or request all available fields.

Discussed at 6:17

Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.

More videos from Wagtail CMS