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_adhoc_queries()[source]

Returns a list of ad hoc queries.

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_resource_fields()[source]

Returns a list of resource fields

classmethod get_tasks()[source]

Returns endpoint tasks

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 from BaseEndpointDefinition

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 the is_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 to None.

classmethod documentation()[source]

Returns a dictionary containing class name, fields, and consumer type. Used for documentation purposes.

classmethod get_consumer_attributes()[source]

Returns a list of consumer attributes

classmethod get_consumer_type()[source]

Returns consumer type. If consumer is set to None it will return unknown.

is_permitted()[source]

Checks whether user has permission to access the resource.

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 for GET.

consumer

Initialize consumer using request_attribute(). It can also be set to None.

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 and PUT.

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()