简体   繁体   English

DRF:方法GET基于参数返回对象

[英]DRF: Method GET return objects based on parameter

I am learning Django and am trying to build an endpoint that returns the objects based on a parameter given in the URL. 我正在学习Django,并且我正在尝试构建一个端点,该端点根据URL中给出的参数返回对象。

Currently I have these URLS: 目前我有这些URL:

/api/v1/ as root which returns: /api/v1/作为root返回:

GET /api/v1/

HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "device-groups": "http://127.0.0.1:8000/api/v1/device-groups/"
}

/api/v1/device-groups/ which returns all the device groups: /api/v1/device-groups/返回所有设备组:

HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "device_group_name": "Default",
        "group_uuid": "7465febe-7c46-4420-85a1-73dfe0af812c",
        "color": "4286f4",
        "is_default": true,
        "customer": {
            "customer_name": "Customer1",
            "customer_uuid": "b3eb5d7d-d1a8-4997-a65b-28bed71b7cc6"
        }
    },
    {
        "device_group_name": "Default",
        "group_uuid": "e12d02d0-7916-477e-b318-9680a38617db",
        "color": "4286f4",
        "is_default": true,
        "customer": {
            "customer_name": "Another customer",
            "customer_uuid": "5b5dafab-c311-4f58-80f5-c50d77fcf8a5"
        }
    },
    {
        "device_group_name": "group of customer1",
        "group_uuid": "c72e87b1-e7c8-4dcd-a9c7-4f6a016d7676",
        "color": "#ffffff",
        "is_default": false,
        "customer": {
            "customer_name": "Customer1",
            "customer_uuid": "b3eb5d7d-d1a8-4997-a65b-28bed71b7cc6"
        }
    }
]

I want an endpoint like /api/v1/device-groups/<customer_uuid>/ which returns the device groups that are related to the given customer_uuid. 我想要一个像/api/v1/device-groups/<customer_uuid>/这样的端点,它返回与给定customer_uuid相关的设备组。

My serializers.py : 我的serializers.py

class CustomerSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Customer
        fields = ('customer_name', 'customer_uuid')


class DeviceGroupSerializer(serializers.HyperlinkedModelSerializer):
    customer = CustomerSerializer(many=False, read_only=True)

    class Meta:
        model = DeviceGroup
        fields = ('device_group_name', 'group_uuid', 'color', 'is_default', 'customer')

My views.py : 我的views.py

class DeviceGroupViewSet(viewsets.ModelViewSet):
    serializer_class = DeviceGroupSerializer
    queryset = DeviceGroup.objects.all()

My urls.py : 我的urls.py

router = routers.DefaultRouter()
router.register(r'device-groups', views.DeviceGroupViewSet)


urlpatterns = [
   path('admin/', admin.site.urls),
   path('api/v1/', include(router.urls)),
]

I tried overriding get_queryset like this: 我尝试像这样覆盖get_queryset

def get_queryset(self):
    customer = self.request.GET['customer']
    queryset = DeviceGroup.objects.filter(customer=customer)
    return queryset

But it results in: AssertionError: basename argument not specified, and could not automatically determine the name from the viewset, as it does not have a .queryset attribute. 但它导致: AssertionError: basename argument not specified, and could not automatically determine the name from the viewset, as it does not have a .queryset attribute.

What do I need to change to get an /api/v1/device-groups/<customer_uuid>/ endpoint which only shows device groups that are related to the given customer_uuid? 我需要更改以获取/api/v1/device-groups/<customer_uuid>/ endpoint,它只显示与给定customer_uuid相关的设备组?

EDIT 编辑

Internal Server Error: /api/v1/device-groups/
Traceback (most recent call last):
File "C:\Users\Stevy\PycharmProjects\tapartisan-api\env\lib\site- 
packages\django\utils\datastructures.py", line 77, in __getitem__
list_ = super().__getitem__(key)
KeyError: 'customer'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "C:\Users\Stevy\PycharmProjects\tapartisan-api\env\lib\site- 
packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\Stevy\PycharmProjects\tapartisan-api\env\lib\site- 
packages\django\core\handlers\base.py", line 126, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\Stevy\PycharmProjects\tapartisan-api\env\lib\site- 
packages\django\core\handlers\base.py", line 124, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Stevy\PycharmProjects\tapartisan-api\env\lib\site- 
packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "C:\Users\Stevy\PycharmProjects\tapartisan-api\env\lib\site- 
packages\rest_framework\viewsets.py", line 116, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\Stevy\PycharmProjects\tapartisan-api\env\lib\site- 
packages\rest_framework\views.py", line 495, in dispatch
response = self.handle_exception(exc)
File "C:\Users\Stevy\PycharmProjects\tapartisan-api\env\lib\site- 
packages\rest_framework\views.py", line 455, in handle_exception
self.raise_uncaught_exception(exc)
File "C:\Users\Stevy\PycharmProjects\tapartisan-api\env\lib\site- 
packages\rest_framework\views.py", line 492, in dispatch
response = handler(request, *args, **kwargs)
File "C:\Users\Stevy\PycharmProjects\tapartisan-api\env\lib\site- 
packages\rest_framework\mixins.py", line 40, in list
queryset = self.filter_queryset(self.get_queryset())
File "C:\Users\Stevy\PycharmProjects\tapartisan-api\app\core\views.py", line 
13, in get_queryset
customer = self.request.GET['customer']
File "C:\Users\Stevy\PycharmProjects\tapartisan-api\env\lib\site- 
packages\django\utils\datastructures.py", line 79, in __getitem__
raise MultiValueDictKeyError(key)
django.utils.datastructures.MultiValueDictKeyError: 'customer'`

Router could not determine basename . 路由器无法确定basename You have to define a basename in your router. 您必须在路由器中定义基basename Like this 像这样

router.register(r'device-groups', views.DeviceGroupViewSet, base_name='device-groups')

base_name is actually used to generate names for routes / urls. base_name实际上用于生成routes / url的名称。 You can read more about it here . 你可以在这里阅读更多相关信息。

I am not familiar with DRF but in general in order to get the object based on a parameter you have to: 我不熟悉DRF,但一般来说,为了根据您必须参数获取对象:

1) Define your url in such a way to take in mind the customer_uuid you are going to type dynamically when you want to build your endpoint So, with the help of regex you have to build something like: 1)以这种方式定义你的url,记住你想要构建你的端点时动态输入的customer_uuid所以,在regex的帮助下,你必须构建如下内容:

url(r'^/api/v1/device-groups/(?P<customer_uuid>\d+)/$', views.your_view, name='your_view')

The regex \\d+ will match an integer of arbitrary size. 正则表达式\\ d +将匹配任意大小的整数。 This integer will be used to retrieve the Customer from the database. 此整数将用于从数据库中检索Customer。 Now observe that I wrote the regex as (?P\\d+), this is telling Django to capture the value into a keyword argument named customer_uuid. 现在观察我将正则表达式写成(?P \\ d +),这告诉Django将值捕获到名为customer_uuid的关键字参数中。

2) Define your view function 2)定义您的视图功能

from django.shortcuts import render, get_object_or_404
from .models import Customer

def your_view(request, customer_uuid):
    customer = get_object_or_404(Customer, pk=customer_uuid)
    return render(request, 'customer.html', {'customer': customer})

Hope it helps 希望能帮助到你

You should get what you want if you define a different lookup_field in the view like: 如果在视图中定义不同的lookup_field,您应该得到您想要的内容,如:

class DeviceGroupViewSet(viewsets.ModelViewSet):
    serializer_class = DeviceGroupSerializer
    queryset = DeviceGroup.objects.all()
    lookup_field = 'customer_uuid'

Or maybe you'dl like to take a look to this documentation to consider a different approach. 或者您可能希望查看本文档以考虑不同的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM