Django REST框架:何时创建超链接资源,何时创建嵌套资源?如何对嵌套资源进行POST



我正在使用Django REST框架构建一个REST-web API。事情进展顺利,但我偶然发现了嵌套资源的问题。起初,REST API中的所有关系都是超链接的。例如,一个帖子看起来是这样的:

{
    "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
}

帖子和作者(用户)之间的关系是超链接的。当你想创建一个新的帖子时,你需要为特定用户指定一个正确的超链接——这很好。

当调用一个帖子列表时,效率会变低,因为你必须为每个帖子的每个作者做一个额外的API调用。我通过使用NESTED资源而不是HYPERLINKED资源解决了这个问题,所以现在每个帖子都包含了关于作者的所有信息。

{
    "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
}

我的第一个问题是:你有一个指导方针吗,我应该创建一个嵌套的数据结构,还是一个带有超链接的单独端点

我的第二个问题是:当我使用author作为嵌套资源并想要创建一个新帖子时,我不想指定关于作者的所有信息(用户名、电子邮件…)。有没有办法只使用指向用户的链接来进行create/UPDATE操作?或者修改一些内容,使用户ID足以填写此字段?

如果我正确理解你的问题,你想在检索数据时扩展author,只想在更新和创建时发送ID或URL。

1#这与任何指导原则无关,完全取决于您对如何使用api的要求。

2#所以您需要扩展您的UserSerializer并覆盖to_internal_value。示例代码可能看起来像

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)

请注意您必须有一个用于用户详细信息的Endpoint才能使用HyperLinkedRelatedField。

因此,如果您希望能够发送ID,那么示例代码可能看起来像

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)

然而,我希望在POST/PUT/PATCH中发送ForeignKey字段时保持一致性。(总是URL或ID)。

然后像一样在代码中使用它

class PostSerializer(serializers.HyperlinkedModelSerializer):
    author = MyCustomSerializer()
    class Meta:
        model = Post

请参阅有关嵌套资源上可写入POST的嵌套序列化程序的文档。