简体   繁体   English

如何通过Django Rest Framework公开非模型模块方法?

[英]How to expose non-model module methods via Django Rest Framework?

I am using Django Rest Framework to create an API. 我正在使用Django Rest Framework来创建API。 There are model classes such as City which are exposed via the API. 有一些模型类,如City ,通过API公开。 Now I created a utils module with a few useful methods: 现在我创建了一个带有一些有用方法的utils模块:

# city/utils.py

def distance_between_cities(city1, city2):
    return city1.distance(city2)

I want to expose the example method distance_between_cities as an API endpoint. 我想将示例方法distance_between_cities公开为API端点。 So I started off by creating a view: 所以我开始创建一个视图:

# city/views.py
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from . import utils

class DistanceView(APIView):

    def get(self, request, format=None):
        city1 = request.query_params.get('city1', None)
        city2 = request.query_params.get('city2', None)
        distance = utils.distance_between_cities(city1, city2)
        distance_hash = {'distance': distance}
        return Response(distance_hash, status=status.HTTP_200_OK)

Then I tried to register a route: 然后我试着注册一条路线:

# city/urls.py
from rest_framework.routers import DefaultRouter
from . import views

router = DefaultRouter()
router.register(r'distance', views.DistanceView)

When I visit the website the following error is shown: 当我访问该网站时,显示以下错误

base_name argument not specified, and could not automatically determine the name from the viewset, as it does not have a .queryset attribute. base_name参数未指定,并且无法自动确定视图集中的名称,因为它没有.queryset属性。

I would like to see the endpoint in the website rendered by DRF similar to other (model related) endpoints. 我希望看到DRF呈现的网站中的端点与其他(模型相关的)端点类似。

DRF API网站

Finally, I would like to access the endpoint via: 最后,我想通过以下方式访问端点:

http://localhost:8000/api/cities/distance.json?city1=23&city1=42

I tried to inspect the API via curl : 我试图通过curl检查API:

$ curl -X HEAD -i http://localhost:8000/api/cities/distance.json?city1=23&city2=42

This is the response header: 这是响应头:

HTTP/1.0 404 NOT FOUND
Date: Fri, 09 Oct 2015 16:45:06 GMT
Server: WSGIServer/0.2 CPython/3.4.3
X-Frame-Options: SAMEORIGIN
Content-Type: application/json
Vary: Accept, Cookie
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS

Useful links 有用的链接

If you need the new entry point to be listed, you'll need to inherit from a ViewSet (note that I'm not speaking about ModelViewSet). 如果需要列出新的入口点,则需要从ViewSet继承(请注意,我不是在谈论ModelViewSet)。

I wrote a short guide + sample project on how to do that here: https://medium.com/@linovia/django-rest-framework-viewset-when-you-don-t-have-a-model-335a0490ba6f 我在这里写了一篇关于如何做到这一点的简短指南+示例项目: https//medium.com/@linovia/django-rest-framework-viewset-when-you-don-t-have-a-model-335a0490ba6f

You won't need all the ViewSet methods, probably just the list one according to your comments. 您不需要所有ViewSet方法,可能只需根据您的注释列出一个。

in your urls.py, you're giving router.register() a DistanceView, which is of type APIView, But you'll have to specify a ViewSet for that. 在你的urls.py中,你给的是router.register()一个DistanceView,它的类型是APIView,但是你必须为它指定一个ViewSet。

django-rest-framework can only determine url mapping for ViewSets. django-rest-framework只能确定ViewSets的url映射。 So instead you can manually map the url, like you would do with default django apps. 因此,您可以手动映射网址,就像使用默认的django应用程序一样。

urls.py urls.py

urlpatterns = [
    url(r'distance', views.DistanceView),
]

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

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