【问题标题】:Filtering Django ModelViewSet List From Url Parameter从 URL 参数中过滤 Django ModelViewSet 列表
【发布时间】:2017-11-16 01:21:35
【问题描述】:

您好,我有一个类似的模型:

class Appointment(models.Model):
    hospital = models.ForeignKey(Hospital, on_delete=models.CASCADE)
    patient = models.ForeignKey(Patient, on_delete=models.CASCADE)

我的视图如下:

class AppointmentViewSet(viewsets.ModelViewSet):
    queryset = Appointment.objects.all()
    serializer_class = AppointmentSerializer

在我的网址中:

router.register(r'appointments', AppointmentViewSet)

现在我想按一些患者 ID 过滤预约列表。此 id 应由请求者通过 url 提供。我正在考虑使用 kwargs 来捕捉它。但我不知道该怎么做。我知道我必须重写 list 方法。

def list(self, request, *args, **kwargs):
    # what do I write here? so that the queryset would be filtered by patient id sent through the url? 

如何自定义 url 和/或 view 以适应患者 ID 参数?我只想修改列表请求,所有其他操作(创建、详细信息、销毁)应由模型视图集的默认行为处理。

谢谢。

【问题讨论】:

  • 提供id后,需要实例还是列表?
  • 一个列表。约会清单。
  • 你是从 url 传递 id 的,对吧?

标签: python django url keyword-argument django-rest-viewsets


【解决方案1】:

这是我最终的做法:

我添加了一个这样的 url 条目:

url(r'appointments/ofpatient/(?P<patient>\d+)', AppointmentViewSet.as_view({'get': 'list'})),

我可以从浏览器调用:

http://localhost:8000/appointments/ofpatient/6

在视野中:

def list(self, request, patient=None):
    if patient:
        patient = Patient.active.filter(id=patient)
        appts = Appointment.active.order_by('appt_time').filter(patient=patient)
        serializer = self.get_serializer(appts, many=True)
        return Response(serializer.data)
    else:
        appts = Appointment.active.order_by('appt_time')
        serializer = self.get_serializer(appts, many=True)
        return Response(serializer.data)

这样,/appointments url 也被保留了下来。

【讨论】:

    【解决方案2】:

    您可以定义一个自定义方法来处理带有患者 ID 的 url 的路由:

    from rest_framework.decorators import list_route
    rom rest_framework.response import Response
    
    class AppointmentViewSet(viewsets.ModelViewSet):
        ...
    
        @list_route()
        def patient_appointments(self, request, id=None):
            serializer = self.get_serializer(queryset.filter(patient_id=id), many=True)
            return Response(serializer.data)
    

    list_route 装饰器将您的方法标记为需要路由。

    更新:

    您可以手动将网址注册为:

    url(r'^(?P<id>[0-9]+)/appointments/$', AppointmentViewSet.as_view({'get': 'patient_appointments'}), name='patient-appointments')
    

    【讨论】:

    • 在这种情况下我的请求 url 应该是什么样子?
    • 你的意思是 /appointments/?但这有一个问题。这种 url 格式应该提供“详细”视图。我将如何通过它传递患者 ID?
    • 它与详细视图不冲突,有一个尾随appointments。我建议您在第二次猜测之前先尝试一下。如果您有任何错误/问题,请反馈。
    • 我试过这个网址:url(r'(\d+)/appointments/', AppointmentViewSet.as_view({'get': 'list'})),但它忽略了开始并给我所有的记录
    • 我已经更新了答案。视图应该是从patient_appointments方法构造的,而不是list,但是我不知道你为什么要自己写url conf。
    【解决方案3】:

    试试

    if(self.request.get('pid')):
        pk = self.request.get('pid')
        all_appointment = Appointment.objects.filter(patient__pk=pk)
    

    对于患者的 url 将是 appoinment/?pid=9

    预约详情appoinment/9

    【讨论】:

    • 那我在网址里写什么?我应该如何发出请求?
    • 正如你所说的你想传递 id,所以约会/1 或 2 类似的东西
    • 但由于我使用的是模型视图集,所以预约后的任何 id 都被视为预约记录本身的 id,而不是患者 id。
    • 好的,所以你可以做一件事,你可以从约会 id 中获取患者 id,然后可以根据该用户 id 进行过滤
    • 实际上我正在尝试检索患者的所有约会。所以必须先获取患者ID。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-01
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 2014-10-01
    • 2018-01-02
    • 2016-03-22
    相关资源
    最近更新 更多