问题
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": "broak@gmail.com"
"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?
回答1:
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.
来源:https://stackoverflow.com/questions/26899976/django-rest-framework-when-to-create-a-hyperlinked-resource-and-when-nested-res