The DRF provides ways to serialize related objects in your ORM. Objects that refer to each other by foreign keys can be identified by an ID. You can also nest serialization by having related objects contained within one another. This time around, I’m going to continue using the
vehicles app from the previous lesson.
You can follow along with the new models, serializers, views, and urls files as shown. If you desire, you can create an
admin.py file to go along with the models that are there, or use the one in the supplementary materials. Don’t forget to run
migrate as necessary to get your models into the database.
And of course, you’ll want some data to play with. You can either use the admin or the
loaddata command with one of the fixtures in the supplemental materials. Like in the previous lesson, I’m going to use the
models/ directory and create a file called
vehicles inside of it. The
vehicles models file contains two Django definitions, one for a
Vehicle that has a single field
name, and one for a
Part that is related to the
And here’s the serializers file. First off, I want to serialize the
Vehicle. Except for line 18, everything here is what you’ve seen before. The
VehicleSerializer inherits from the
ModelSerializer. On line 21, you indicate that this is serializing a
Vehicle object. On line 22, you list those fields that you’re interested in. Line 18 is what’s different here.
I want to nest the
Part objects inside of the
Vehicle object, and in order to do that, I’m going to add a new field called the
PartSerializer. Because vehicles are related to parts through a part set, the field name here is
You can just create the
Vehicle on its own. You can decide for yourself based on your construction whether you want to create things like parts separately from the vehicles, or do it with a
POST containing a nested object.
PartSerializer is similar to what you’ve seen before. It’s based on
Meta information points it at the Django
Part model, and the
fields listing lists those fields that are going to be included in the
Additionally, I’ve added another field here, which is a custom field called
SerialNumberField is going to create a custom serial number based on other attributes of the
If I wanted to point this at an existing field inside of the
Part, I could set the value of
source to that field. By setting it to asterisk (
"*"), it tells the DRF to just use the field serializer and set the value to whatever the custom field returns. And finally, to tie it all together, here’s the
This is a custom field that inherits from the
serializers.Field object and implements the
.to_representation() method. When called, the representation takes a
value of the thing being serialized, which in this case will be the parent, the
Part, and then lines 7 and 8 take information of that
Part and return a string, which in this case is based on part of the
make field and the
id of the
Part that is serialized will include a
SerialNumberField. Each of those fields will call
make and the
id of the
Part will be combined into a serial number and returned into the serialized object.
Now to create some views for the
Part objects. Like before, I’m creating the
vehicles.py file inside of the
views/ directory. Line 12 declares the
VehicleViewSet. Line 8 declares the
PartViewSet. Both of these specify the serializer that they’re associated with, and the only thing that I’ve done a little different here is shown you a shortcut for creating your queryset. Line 15 and 16 you’ve seen before, which is implementing the
.get_queryset() method of the
It returns all vehicles. Alternatively, you can do the same thing by setting the
.queryset attribute like I’ve done in line 10. If your queryset is simple, like all objects, the
.queryset attribute is the better way to do this.
This time, I’ve done something that I haven’t done in a while. I’m visiting the
vehicles/ base URL. Because the router has registered multiple URLs inside of it, when you hit the base URL, the router shows you all of the possible children.
This is a convenient way of getting meta information about what your interface provides. Unfortunately, it only works with the router, so the
list_tools() method that I created in the previous lesson doesn’t show up here. It’s still there—it just doesn’t show up in this listing.
06:56 But for those things that are created with a router, you can do this automatically. This in and of itself is an argument for always using ViewSets and using your router so that you can take advantage of this meta information.
I’m going to click on the
"parts" listing, and here you have the data that I loaded before, two parts. If you were paying close attention when I showed you the serializers, you would’ve seen that I didn’t include the
id field this time. I include
If you have queried this and you have the
url available, you can use that
url to do patches or puts or deletes afterwards. This means you don’t have to hardcode the URLs for your objects inside of your application. This is definitely a better way to go.
07:58 There are a couple situations here in which you have to do some extra work to get this URL, but in the vanilla mechanism that I’ve just shown you here, it more or less comes for free. I’ll show you the exceptions in the next lesson.
This is another good reason use the URLs when you’re referencing these objects. Now you’ve got both the vehicle and the part information available to you in the payload. If you want to change the vehicle, you can use the
vehicles/ URL, and if you want to change the part, you can use the
Become a Member to join the conversation.