URL Plugins¶
URL plugins allows a plugin to extend the URLS schema used by Cantemo to enable extra functionality. You can then invoke your own code and views from inside your plugin.
IPluginURL¶
- class portal.generic.plugin_interfaces.IPluginURL¶
IPluginURL plugins are loaded by the URL dispatcher, adding to the URL configuration of Portal.
- Requires:
__init__() method that defines:
name
- human readable name for the pluginurls
- string pointing to a urls.py packageurlpattern
- root URL to use for the end-pointsnamespace
- Django view namespace for the registered endpointsinclude_in_api_docs
(optional) - if set to True the end-points are included in REST API Reference
A simple example in a file called plugin.py that would matchup to a urls.py file in your plugin package:
from portal.pluginbase.core import Plugin
from portal.generic.plugin_interfaces import IPluginURL
class MyURLPlugIn(Plugin):
""" Adds extra URLS for the testapp plugin.
"""
implements(IPluginURL)
def __init__(self):
self.name = "My URL Plugin"
self.urls = 'portal.plugins.testapp.urls'
self.urlpattern = r'^testapp/'
self.namespace = 'testapp'
pluginurls = MyURLPlugIn()
That plugin would load urls from portal.plugins.testapp.urls
, a
urls.py file in a folder called testapp within the plugins
installation directory. As with normal python packages an __init__.py
should be created in the testapp folder. Within this, import the file
containing the plugin so that the plugin system is aware of the Plugin
contained in plugin.py:
from portal.plugin import *
urls.py
is a normal Django URLconf, for example:
from django.conf.urls.defaults import *
portal.plugins.testapp.views import test_view
urlpatterns = [
url(r'^/$', test_view, {'message': 'sample root page'}, name='sample-root'),
url(r'^test/$', test_view, kwargs={'message': 'sample test page'}, name='sample-settings'),
]
These urlpatterns use testapp.views (views.py in your testapp folder) to dispatch the HttpResponse. More information on views and urls can be obtained from the Django documentation, https://docs.djangoproject.com/
Including plugin end-points in REST API Reference¶
Note
This feature is a beta, meaning backwards incompatible changes may be introduced in future releases.
The optional include_in_api_docs
parameter in IPluginURL
makes the registered URLs show up
in Cantemo REST API Reference (e.g. https://<your Cantemo URL>/APIdoc/
). The end-points can also be interacted with
from that documentation view.
Note that only portal.generic.baseviews.CView
or rest_framework.views.APIView
based views are included
in the documentation.
An example, plugin.py
:
from portal.generic.plugin_interfaces import IPluginURL
from portal.pluginbase.core import Plugin
from portal.pluginbase.core import implements
class ApiDocTestPluginURL(Plugin):
implements(IPluginURL)
def __init__(self):
self.name = "APIdoc test URL plugin"
self.urls = "portal.plugins.api_doc_test.urls"
self.urlpattern = "^API/v2/api_doc_test/"
self.namespace = "api_doc_test"
self.plugin_guid = "372e47a5-74a2-4821-a388-d3c4458ddda2"
self.include_in_api_docs = True
ApiDocTestPluginURL()
This add alls the URLs from the Python package portal.plugins.api_doc_test.urls
to the system, available under
API/v2/api_doc_test/
, and also includes them in the documentation.
This urls.py
registers two views. Note the use of the more modern path()
instead of url()
:
from django.urls import path
from .views import IndexView
from .views import InstanceView
urlpatterns = [
path("", IndexView.as_view(), name="index"),
path("instance/<instance_id>/", InstanceView.as_view(), name="instance"),
]
This is views.py
implementation:
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from portal.generic.baseviews import CView
class IndexView(CView):
renderer_classes = (JSONRenderer,)
def get(self, request):
"""
Get the API doc test index
"""
return Response({"detail": "This is the index"})
class InstanceView(CView):
renderer_classes = (JSONRenderer,)
def get(self, request, instance_id):
"""
Get "data" for a single instance.
"""
return Response({"data": f"This is data for instance {instance_id}", "id": instance_id})
def put(self, request, instance_id):
"""
Update data on an instance
Does not actually store the data. Any JSON sent in the request is returned.
---
parameters:
- name: body
description: A JSON object for updated data on the instance
type: object
required: true
paramType: body
"""
return Response({"detail": f"Updated data for instance {instance_id}", "data": request.data, "id": instance_id})
Docstrings from the get/put
functions are included in the documentation. Path parameters are included in the
documentation as arguments automatically, others (body, query) can be described in the docstring as shown above.