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
BaseEndpointDefinitionclass. 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_attributesto 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_authorizedperforms 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_authorizedimplementation should be overridden by the endpoint definition inheriting fromBaseEndpointDefinitionDefault Value |
FalseExample: 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_validto express it.An alternative to
is_validwould be to use the@fieldas a decorator on a function and express this restriction there.Default Value |
TrueExample
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
Noneif 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.resourceunless 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:
BaseEndpointDefinitionThis 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
consumerand_consumer_typetoNone.
- 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
Noneit 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:
EndpointDefinitionIt is a specialization of
EndpointDefinitionthat performs queries on the URL. It can be used when defining endpoints bound to models.ResourceEndpointDefinitionis 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:
ResourceEndpointDefinitionHandles the changes to the resource that happened from the request, and saves the resource. It can be used for
POSTandPUT.
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()