我一直在用Django编写一个webapp来取代我和一些朋友玩的基于电子表格的笨拙运动采摘游戏。我学到了很多东西,并且很快就认识了Django以及如何从头开始构建这样的东西。
我最近意识到我想在前端使用更强大的功能(Ember,Angular等),最终目标是单页应用。为此,我安装了Django REST Framework(DRF)并开始阅读文档并遵循教程。这非常有趣,我终于开始明白为什么带有API的客户端 - 服务器模型真的是实现全面平滑交互的唯一方法。
我正在尝试将我的一个基于类的视图实现为API端点,并且我在构思它时遇到了很多麻烦。我以为我会从一个简单的,仅限GET的端点开始 - 这是我试图以API形式复制的简单CBV:
class MatchupDetail(DetailView):
template_name = 'app/matchups.html'
context_object_name = 'pick_sheet'
def get_object(self):
#logic to find and return object
def get_opponent(self,username,schedule,week, **kwargs):
#logic to find and return the opponent in the matchup
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
#logic to pull the opponents details and set them in the context
我觉得我已经掌握了这个流程 - 用户点击了一个链接,这个视图检索所请求页面核心的对象,用上下文中的内容补充它,然后呈现它。
当我开始考虑将其转变为API端点时,它没有多大意义。我是否应该将所有与用户相关的数据放入单个JSON响应中?或者前端基本上应该处理这个逻辑的流程,而API只是由一组端点组成 - 例如,一个用于检索对象,一个或多个用于检索现在在上下文中传递的内容?
上述观点的我的(超级基本)API实现有什么问题促使我发布这篇文章:
class MatchupDetailApi(generics.ListAPIView):
queryset = Sheet.objects.all()
serializer_class = SheetSerializer
使用序列化程序:
class SheetSerializer(serializers.ModelSerializer):
user = serializers.ReadOnlyField()
class Meta:
model = Sheet
当我注意到没有它时,我添加了用户字段,返回的序列化Sheet对象实际上只是数据库中的行 - 整数ID,User对象的整数外键,依此类推。使用“传统”CBV,整个对象将返回到模板 - 因此访问相关字段非常直观,而使用Django,也可以轻松遍历对象关系。
REST实现是否提供相同的功能?从我读过的内容来看,似乎我需要对DRF(django-rest-multiple-models)进行扩展,以便在单个响应中返回多个模型,这使我认为我应该为每个模型创建端点模型,并在我处理前端时留下表示逻辑。那是典型的吗? 或者让API端点返回类似对象和几个相关对象的东西是否可行?
注意:当我将用户添加到SheetSerializer时,上面的基本端点停止工作。我意识到我应该有一个UserSerializer,它是:
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
但是,当我尝试浏览API时,我得到一个TypeError,第一个用户不可序列化。具体来说:<User: dkhaupt> is not JSON serializable
。这不是UserSerializer的用途吗?
答案 0 :(得分:2)
让API端点返回类似的东西是否可行 一个对象和几个相关的对象?
是!
这听起来像是一个很好的开始。我会把它构造成这样的东西:
class UserSerializer(serializers.ModelSerializer):
"""serializes a user"""
class Meta:
model = User
fields = ('id', 'first_name', 'last_name',)
class SheetSerializer(serializers.ModelSerializer):
"""serializes a sheet, and nests user relationship"""
user = UserSerializer(read_only=True)
class Meta:
model = Sheet
fields = ('id', 'sheet_name', 'user',)
我认为你不需要django-rest-multiple-models来实现你想要达到的目标。在我的草图中(我猜测字段名称),您将序列化工作表以及相关的用户对象。
答案 1 :(得分:1)
您可以使用来源属性从其他相关模型添加字段。
例如:
class SheetSerializer(serializers.ModelSerializer):
user_id = serializers.ReadOnlyField(source='user.user_id')
username = serializers.ReadOnlyField(source='user.username')
class Meta:
model = Sheet
此处序列化程序将返回与Sheet模型相关的用户模型中的信息。