Endpoint Definitions¶
Once EndpointBinder
binds a request to an EndpointDefinition
, the request is then processed by the endpoint definition.
An important concept in endpoint definitions is resource
. Resources are abstract representations of underlying objects that are exposed by an API. They may or
may not be tied to a model.
Note
Important: Throughout the document, resource
is referring to <endpoint_definition>.resource()
.
Built-in Endpoint Definitions¶
There are four built-in DDA endpoint definitions with different functionalities that a developer can inherit from to construct their own endpoint definitions.
1. BaseEndpointDefinition¶
- class django_declarative_apis.machinery.BaseEndpointDefinition[source]¶
The base class for implementing Endpoints. At the very least a developer needs to inherit from
BaseEndpointDefinition
class. This is how the EndpointBinder will know how to communicate with the endpoint and query its fields.- classmethod documentation()[source]¶
Returns a dictionary containing the class name and endpoint fields that can be used for documentation purposes.
Example:
{'class_name': 'TodoUpdateSingleTaskDefinition', 'fields': [{'name': 'request'}, {'name': 'task', 'type': <class 'str'>, 'multivalued': False}, {'name': 'priority', 'type': <class 'str'>, 'multivalued': False}, {'name': 'completion_status', 'type': <class 'bool'>, 'multivalued': False, 'default_value': False} ], 'consumer_type': 'unknown'}
- finalize()[source]¶
Called immediately before a response is returned. Override this method in an Endpoint Definition to perform any clean-up not handled automatically by the framework.
- classmethod get_endpoint_attributes()[source]¶
Returns a list of endpoint attributes
Example Let’s define an endpoint that updates a single task in a todo list.
from django_declarative_apis import machinery class TodoUpdateSingleTaskDefinition( TodoResourceMixin, machinery.ResourceEndpointDefinition, ): task = field(required=True, type=str) priority = field(required=True, type=str) completion_status = field(type=bool, default=False) resource_id = url_field(name='id') @endpoint_resource(type=Todo) def resource(self): task = Todo.objects.get(id=self.resource_id) task.task = self.task task.priority = self.priority task.completion_status = self.completion_status task.save() return task
Using
get_endpoint_attributes
to find all the attributes of this endpoint and print it:endpoint_object = resources.TodoUpdateSingleTaskDefinition attributes = endpoint_object.get_endpoint_attributes() for attribute in attributes: print(attribute.name) # It will print: # request # task # priority # completion_status # resource_id # resource
- classmethod get_request_fields()[source]¶
Returns a list of request fields
Example
endpoint_object = resources.TodoUpdateSingleTaskDefinition fields = endpoint_object.get_request_field() for field in fields: print(field.name) # It will print: # request # task # priority # completion_status
- classmethod get_request_properties()[source]¶
Returns a list of request properties
Example
endpoint_object = resources.TodoUpdateSingleTaskDefinition properties = endpoint_object.get_request_properties() for property in properties: print(property.name) # It will print: # request # task # priority # completion_status
- classmethod get_required_request_fields()[source]¶
Returns a list of required request fields
Example
endpoint_object = resources.TodoUpdateSingleTaskDefinition properties = endpoint_object.get_required_request_fields() for property in properties: print(property.name) # It will print: # task # priority
- classmethod get_required_request_properties()[source]¶
Returns a list of required request properties
Example
endpoint_object = resources.TodoUpdateSingleTaskDefinition properties = endpoint_object.get_required_request_properties() for property in properties: print(property.name) # It will print: # request # task # priority
- classmethod get_url_fields()[source]¶
Returns a list of URL fields
Example
endpoint_object = resources.TodoUpdateSingleTaskDefinition url_fields = endpoint_object.get_url_fields() for field in url_fields: print(field.name) # It will print: # resource_id
- property http_status¶
Returns a HTTP 200 OK success status.
- abstract is_authorized()[source]¶
The authentication layer of DDA that is tied to the resource adapter is only responsible for validating the requester. We still need to determine whether the requester is authorized to perform certain actions, which is the reason behind implementation of
is_authorized
.is_authorized
performs an authorization check on the request to decide whether or not the user should have access to the resource and returns a boolean value.is_authorized
implementation should be overridden by the endpoint definition inheriting fromBaseEndpointDefinition
Default Value |
False
Example: To implement an open API, set the is_authorized to always return True.
from django_declarative_apis import machinery class SampleEndpointDefinition(machinery.BaseEndpointDefinition): def is_authorized(self): return True
- is_permitted()[source]¶
Similar to
is_authorized
, it checks whether a user has the permission to access the resource. Returns a boolean value.Default Value |
True
- is_valid()[source]¶
Used in scenarios where a request binds correctly but there are combination of parameters that would make the request invalid. Returns a boolean value.
For example, if the valid value for a field is from 1 to 10, this cannot be expressed through
field
. However, we can use theis_valid
to express it.An alternative to
is_valid
would be to use the@field
as a decorator on a function and express this restriction there.Default Value |
True
Example
from django_declarative_apis import machinery class SampleEndpointDefinition(machinery.BaseEndpointDefinition): valid_int = field(required=True, type=int) def is_authorized(self): return True def is_valid(self): if self.valid_int < 1 or self.valid_in > 10: raise ValueError return True
- rate_limit_key()[source]¶
Returns a unique key used for rate-limiting requests to this endpoint. Returns
None
if the request should not be rate-limited.Default Value |
None
- rate_limit_period()[source]¶
Specifies and returns the number of seconds to enforce between requests with the same
rate_limit_key
.Default Value | 1
- abstract property resource¶
Instance of a resource should either be a dictionary or instance of a Django Model or QuerySet.
This property must be implemented by all endpoint definitions. If not implemented, it will raise a NotImplementedError.
Note
Important: The DDA framework will by default return self.resource as the response, unless response is overridden to return something else.
Example
from django_declarative_apis import machinery class TodoDefinition(machinery.BaseEndpointDefinition): resource_model = Todo @endpoint_resource(type=Todo) def resource(self): return Todo.objects.all()
- property response¶
By default it returns
self.resource
unless it is overridden.
- property response_filter¶
Returns the filter that will be applied to the response.
2. EndpointDefinition¶
- class django_declarative_apis.machinery.EndpointDefinition[source]¶
Bases:
BaseEndpointDefinition
This base class can be used for implementing endpoints that are not tied to a model. It also implements a basic consumer-based authentication.
- _consumer_type¶
Defines the consumer type with the default privileges of read and write.
Note
If you do not want to define a consumer for your api, set
consumer
and_consumer_type
toNone
.
- classmethod documentation()[source]¶
Returns a dictionary containing class name, fields, and consumer type. Used for documentation purposes.
- classmethod get_consumer_type()[source]¶
Returns consumer type. If consumer is set to
None
it will return unknown.
- is_read_only = False¶
Determines whether the consumer has read-only privileges or not.
Default Value |
False
- request¶
Initialize request using
RawRequestObjectProperty()
3. ResourceEndpointDefinition¶
- class django_declarative_apis.machinery.ResourceEndpointDefinition(*args, **kwargs)[source]¶
Bases:
EndpointDefinition
It is a specialization of
EndpointDefinition
that performs queries on the URL. It can be used when defining endpoints bound to models.ResourceEndpointDefinition
is mainly used forGET
.- consumer¶
Initialize consumer using
request_attribute()
. It can also be set toNone
.
- resource_id¶
The ID of the resource being fetched from the URL or being updated.
- resource_model = None¶
The model to attach to the resource endpoint definition. It must extend or implement the Django ORM model interface as required.
4. ResourceUpdateEndpointDefinition¶
- class django_declarative_apis.machinery.ResourceUpdateEndpointDefinition(*args, **kwargs)[source]¶
Bases:
ResourceEndpointDefinition
Handles the changes to the resource that happened from the request, and saves the resource. It can be used for
POST
andPUT
.
Helper Functions¶
- class django_declarative_apis.machinery.attributes.RawRequestObjectProperty(*args, additional_safe_fields=(), **kwargs)[source]¶
Creates a request object for an endpoint definition.
Example
from django_declarative_apis.machinery import RawRequestObjectProperty request = RawRequestObjectProperty()
- class django_declarative_apis.machinery.attributes.ConsumerAttribute(*args, field_name=None, **kwargs)[source]¶
Creates a requester/authenticator object for an endpoint definition.
Example
from django_declarative_apis.machinery import consumer_attribute requester = consumer_attribute()
- class django_declarative_apis.machinery.attributes.RequestAttribute(attribute_getter=None, required=True, default=None, **kwargs)[source]¶
Used to initialize a consumer object for an endpoint definition.
Example
from django_declarative_apis.machinery import request_attribute consumer = request_attribute()