I'm building a REST web API using the Django REST Framework. Things are going great, but I have, however stumbled upon a problem with nested resources. At first, all relationships in the REST API were hyperlinked. A post, for example, looked like this:
{
"path": "http://api.myproject.com/posts/1.json",
"id": 1,
"author": "http://api.myproject.com/users/broak.json",
"image": "/images/posts/cxyUzlPo.jpg",
"header": "Who am I?",
"footer": "I am a champion!",
"date": "2014-11-09 15:16",
"likes": "http://api.myproject.com/posts/1/likes.json",
"comments": "http://api.myproject.com/posts/1/comments.json",
"likes_count": 0,
"comments_count": 0
}
The relationship between the post and the author (user) is hyperlinked. When you want to create a new post, you need to specify a correct hyperlink to a specific user - this works fine.
When calling a list of posts, things become inefficient, because you have to make an extra API call for every author for every post. I solved this by using NESTED resources instead of HYPERLINKED resources, so every post now contains all the information about the author.
{
"path": "http://api.myproject.com/posts/1.json",
"id": 1,
"author": {
"email": "[email protected]"
"username": "broak",
"first_name: "John",
"last_name": "Broak",
"is_staff": False,
"is_active": True,
"last_login": "02-26-2016"
},
"image": "/images/posts/cxyUzlPo.jpg",
"header": "Who am I?",
"footer": "I am a champion!",
"date": "2014-11-09 15:16",
"likes": "http://api.myproject.com/posts/1/likes.json",
"comments": "http://api.myproject.com/posts/1/comments.json",
"likes_count": 0,
"comments_count": 0
}
My first question is: do you have a guideline, whether I should create a nested data structure or a separate endpoint with hyperlink to it.
My second question is: when I use author as a nested resource and want to create a new post, I don't want to specify all the information about the author (username, e-mail, ...). Is there any way to just use a link to a user for the CREATE/UPDATE operation? Or modify something so that the user ID is enough to fill in this field?
In order to complete your app, if you want to code more python / Django code then use Django, to the contrary if you want to code more JavaScript code then use Django restful API. For web application itself I like using Django ,because it is based on python ,it is much cleaner and shorter than js.
basename - The base to use for the URL names that are created. If unset the basename will be automatically generated based on the queryset attribute of the viewset, if it has one. Note that if the viewset does not include a queryset attribute then you must set basename when registering the viewset.
If i understood your question correctly, You want to have expanded author while you are retrieving the data and just want to send ID or URL in case of update and create.
1#
It is not about any guideline and it totally depends on your requirement of how your api
is going to be used.
2#
So you need to extend your UserSerializer
and override to_internal_value
. Sample code might look like
class MyCustomSerializer(UserSerializer):
def to_internal_value(self, data):
# data must be valid user-detail url
return serializers.HyperLinkedRelatedField(queryset=User.objects.all(), view_name='user-detail').to_internal_value(data)
Notice that you must have a Endpoint for user-detail in able to work with HyperLinkedRelatedField.
So If you want to be able to send ID
then sample code might look like
class MyCustomSerializer(UserSerializer):
# data must be valid user id
def to_internal_value(self, data):
return serializers.PrimaryKeyRelatedField(queryset=User.objects.all()).to_internal_value(data)
However i would like to keep consistency in sending ForeignKey field in POST/PUT/PATCH
. (Always Either URL or ID).
then use it in your code like
class PostSerializer(serializers.HyperlinkedModelSerializer):
author = MyCustomSerializer()
class Meta:
model = Post
Please see the documentation on Writable nested serializers to POST
on a Nested resource.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With