如何考虑Django基于普通类的视图与使用REST API

时间:2016-02-04 03:00:54

标签: python angularjs django rest django-rest-framework

我一直在用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的用途吗?

2 个答案:

答案 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模型相关的用户模型中的信息。