我如何在路由器上注册一个视图(不是视图集)?

我正在使用Django REST框架,一直在尝试创建一个返回少量信息的视图,并将其注册到我的路由器上。

我有四个存储信息的模型,并且所有模型都有一个created_time字段。 我正在尝试创建一个视图,该视图在单个视图中返回最近的对象(基于created_time),其中仅返回四个创建时间。

因此,视图中可能的JSON输出看起来像

{
    "publish_updatetime": "2015.05.20 11:53",
    "meeting_updatetime": "2015.05.20 11:32",
    "training_updatetime": "2015.05.20 15:25",
    "exhibiting_updatetime": "2015.05.19 16:23"
}

我也希望在路由器上注册该视图,以便在加载API根目录时它与其余的端点一起出现。

router.register(r'updatetime', views.UpdateTimeView)

这是我尝试使用的四个模型

class Publish(models.Model):
    user = models.ForeignKey(MyUser)
    name = models.CharField(max_length=50)
    created_time = models.DateTimeField( default=datetime.now)

class Meeting(models.Model):
    user = models.ForeignKey(MyUser)
    name = models.CharField(max_length=50)
    file_addr = models.FileField(upload_to=get_file_path)
    created_time = models.DateTimeField(default=datetime.now)

class Training(models.Model):
    user = models.ForeignKey(MyUser)
    name = models.CharField(max_length=50)
    image = models.ImageField(upload_to=get_file_path, max_length=255)
    created_time = models.DateTimeField(default=datetime.now)

class Exhibiting(models.Model):
    user = models.ForeignKey(MyUser)
    name = models.CharField(max_length=50)
    file_addr = models.FileField(upload_to=get_file_path)
    created_time = models.DateTimeField(default=datetime.now)

是否有可能做到这一点? 怎么做?

flytofuture asked 2020-06-29T22:48:31Z
2个解决方案
59 votes

路由器可与ViewSet配合使用,并且不适用于普通视图,但这并不意味着您不能将它们用于普通视图。 通常,它们与模型(和updatetime)一起使用,但在没有它们的情况下,可以使用ViewSet(如果您通常使用get)和list(如果您仅使用ViewSet)来使用它们。

对于列表视图,将请求方法映射到updatetime这样的方法

  • updatetime -> ViewSet
  • updatetime- > ViewSet

对于详细视图(URL中具有主键),请求方法使用以下映射

  • updatetime -> ViewSet
  • updatetime -> ViewSet
  • updatetime -> ViewSet
  • updatetime -> ViewSet

因此,如果要在路由器上的视图中使用这些请求方法中的任何一种,则需要覆盖正确的视图方法(因此updatetime而不是ViewSet)。


现在,具体来说,您通常会使用updatetime

class UpdateTimeView(APIView):

    def get(self, request, format=None):
        latest_publish = Publish.objects.latest('created_time')
        latest_meeting = Meeting.objects.latest('created_time')
        latest_training = Training.objects.latest('created_time')
        latest_exhibiting = Exhibiting.objects.latest('created_time')

        return Response({
            "publish_updatetime": latest_publish.created_time,
            "meeting_updatetime": latest_meeting.created_time,
            "training_updatetime": latest_training.created_time,
            "exhibiting_updatetime": latest_exhibiting.created_time,
        })

可比的updatetime

class UpdateTimeViewSet(ViewSet):

    def list(self, request, format=None):
        latest_publish = Publish.objects.latest('created_time')
        latest_meeting = Meeting.objects.latest('created_time')
        latest_training = Training.objects.latest('created_time')
        latest_exhibiting = Exhibiting.objects.latest('created_time')

        return Response({
            "publish_updatetime": latest_publish.created_time,
            "meeting_updatetime": latest_meeting.created_time,
            "training_updatetime": latest_training.created_time,
            "exhibiting_updatetime": latest_exhibiting.created_time,
        })

请注意两个必需的更改:updatetime-> ViewSetget->list。我还更新了名称,以表明它不仅仅是普通视图(因为ViewSet不能以相同的方式初始化),但这不是必需的。

因此,有了这个新视图,您可以像其他任何方法一样在路由器中注册它。 您在这里需要updatetime,以便可以生成url名称(通常这将从queryset中提取)。

router.register(r'updatetime', views.UpdateTimeViewSet, base_name='updatetime')

因此,现在updatetime端点将在API根目录中可用,您只需调用端点(一个简单的GET请求)就可以获取最新时间。

Kevin Brown answered 2020-06-29T22:52:38Z
0 votes

还有另一种方法:

urlpatterns = [
    # ... 
    url(r'^you_path/', include(router.urls)),
    url(r'^you_path/you_sub_path', views.UpdateTimeView.as_view()),
    # ... 
]

但是像Swagger这样的东西将无法使用

Alexander answered 2020-06-29T22:53:03Z
translate from https://stackoverflow.com:/questions/30389248/how-can-i-register-a-single-view-not-a-viewset-on-my-router