user_tasks package#

Submodules#

user_tasks.admin module#

Django admin configuration for the django-user-tasks models.

class user_tasks.admin.UserTaskArtifactAdmin(model, admin_site)#

Bases: ModelAdmin

Configuration for UserTaskArtifact admin panel.

list_display = ('created', 'uuid', 'status', 'name', 'text')#
list_filter = ('name',)#
property media#
ordering = ('-created',)#
raw_id_fields = ('status',)#
search_fields = ('uuid', 'name', 'text')#
class user_tasks.admin.UserTaskStatusAdmin(model, admin_site)#

Bases: ModelAdmin

Configuration for UserTaskStatus admin panel.

list_display = ('created', 'uuid', 'state', 'user', 'name')#
list_filter = ('state',)#
property media#
ordering = ('-created',)#
readonly_fields = ('parent',)#
search_fields = ('uuid', 'task_id', 'task_class', 'name', 'user__username', 'user__email')#

user_tasks.apps module#

user_tasks Django application initialization.

class user_tasks.apps.UserTasksConfig(app_name, app_module)#

Bases: AppConfig

Configuration for the user_tasks Django application.

name = 'user_tasks'#
ready()#

Register Celery signal handlers.

verbose_name = 'User Tasks'#

user_tasks.conf module#

Custom Django settings for django-user-tasks.

class user_tasks.conf.LazySettings#

Bases: object

The behavior of django-user-tasks can be customized via the following Django settings.

property USER_TASKS_ARTIFACT_FILTERS#

Tuple containing zero or more filters for UserTaskArtifact listing REST API calls.

Each entry should be a Django REST Framework filter backend class object, such as django_filters.rest_framework.DjangoFilterBackend. The default value contains only user_tasks.filters.ArtifactFilterBackend, which allows superusers to see all artifacts but other users to see only those for artifacts they triggered themselves.

property USER_TASKS_ARTIFACT_STORAGE#

File storage backend to use for user_tasks.models.UserTaskStatus.file.

If explicitly set, the setting should be the import path of a storage backend class.

property USER_TASKS_MAX_AGE#

timedelta reflecting the age after which UserTaskStatus records should be deleted.

For this setting to be useful, user_tasks.tasks.purge_old_user_tasks should be configured to run on an appropriate schedule. Note that the age is calculated from task creation, not completion. The default value is 30 days.

property USER_TASKS_STATUS_FILTERS#

Tuple containing zero or more filters for UserTaskStatus listing REST API calls.

Each entry should be a Django REST Framework filter backend class object, such as django_filters.rest_framework.DjangoFilterBackend. The default value contains only user_tasks.filters.StatusFilterBackend, which allows superusers to see all task statuses but other users to see only those for tasks they triggered themselves.

user_tasks.exceptions module#

Custom exception classes.

exception user_tasks.exceptions.TaskCanceledException#

Bases: RuntimeError

Raised to stop task execution when a cancellation command is noticed.

user_tasks.filters module#

Optional Django REST Framework filter backends for the django-user-tasks REST API.

class user_tasks.filters.ArtifactFilterBackend#

Bases: BaseFilterBackend

Default filter for UserTaskArtifact listings in the REST API.

Ensures that superusers can see all artifacts, but other users can only see artifacts for tasks they personally triggered.

filter_queryset(request, queryset, view)#

Filter out any artifacts which the requesting user does not have permission to view.

class user_tasks.filters.StatusFilterBackend#

Bases: BaseFilterBackend

Default filter for UserTaskStatus listings in the REST API.

Ensures that superusers can see all task status records, but other users can only see records for tasks they personally triggered.

filter_queryset(request, queryset, view)#

Filter out any status records which the requesting user does not have permission to view.

user_tasks.models module#

Database models for user_tasks.

class user_tasks.models.UserTaskArtifact(*args, **kwargs)#

Bases: TimeStampedModel

An artifact (or error message) generated for a user by an asynchronous task.

May be a file, a URL, or text stored directly in the database table.

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

created#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

file#

The descriptor for the file attribute on the model instance. Return a FieldFile when accessed so you can write code like:

>>> from myapp.models import MyModel
>>> instance = MyModel.objects.get(pk=1)
>>> instance.file.size

Assign a file object on assignment so you can do:

>>> with open('/path/to/hello.world') as f:
...     instance.file = File(f)
get_next_by_created(*, field=<model_utils.fields.AutoCreatedField: created>, is_next=True, **kwargs)#
get_next_by_modified(*, field=<model_utils.fields.AutoLastModifiedField: modified>, is_next=True, **kwargs)#
get_previous_by_created(*, field=<model_utils.fields.AutoCreatedField: created>, is_next=False, **kwargs)#
get_previous_by_modified(*, field=<model_utils.fields.AutoLastModifiedField: modified>, is_next=False, **kwargs)#
id#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

modified#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

name#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <django.db.models.manager.Manager object>#
status#

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

status_id#
text#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

url#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

uuid#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

class user_tasks.models.UserTaskStatus(*args, **kwargs)#

Bases: TimeStampedModel

The current status of an asynchronous task running on behalf of a particular user.

The methods of this class should generally not be run as part of larger transactions. If they are, some deadlocks and race conditions become possible.

CANCELED = 'Canceled'#
exception DoesNotExist#

Bases: ObjectDoesNotExist

FAILED = 'Failed'#
IN_PROGRESS = 'In Progress'#
exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

PENDING = 'Pending'#
RETRYING = 'Retrying'#
STATE_TRANSLATIONS = {'Canceled': 'Canceled', 'Failed': 'Failed', 'In Progress': 'In Progress', 'Pending': 'Pending', 'Retrying': 'Retrying', 'Succeeded': 'Succeeded'}#
SUCCEEDED = 'Succeeded'#
artifacts#

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

attempts#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

cancel()#

Cancel the associated task if it hasn’t already finished running.

completed_steps#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

created#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

fail(message)#

Mark the task as having failed for the given reason, and save it.

The message will be available as the UserTaskArtifact.text field of a UserTaskArtifact with name “Error”. There may be more than one such artifact for a single UserTaskStatus, especially if it represents a container for multiple parallel tasks.

get_next_by_created(*, field=<model_utils.fields.AutoCreatedField: created>, is_next=True, **kwargs)#
get_next_by_modified(*, field=<model_utils.fields.AutoLastModifiedField: modified>, is_next=True, **kwargs)#
get_previous_by_created(*, field=<model_utils.fields.AutoCreatedField: created>, is_next=False, **kwargs)#
get_previous_by_modified(*, field=<model_utils.fields.AutoLastModifiedField: modified>, is_next=False, **kwargs)#
id#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

increment_completed_steps(steps=1)#

Increase the value of completed_steps by the given number and save, then check for cancellation.

If cancellation of the task has been requested, a TaskCanceledException will be raised to abort execution. If any special cleanup is required, this exception should be caught and handled appropriately.

This method should be called often enough to provide a useful indication of progress, but not so often as to cause undue burden on the database.

increment_total_steps(steps)#

Increase the value of total_steps by the given number and save.

is_container#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

modified#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

name#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <django.db.models.manager.Manager object>#
parent#

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

parent_id#
retry()#

Update the status to reflect that a problem was encountered and the task will be retried later.

set_name(name)#

Give the specified name to this status and all of its ancestors.

set_state(custom_state)#

Set the state to a custom in-progress value.

This can be done to indicate which stage of a long task is currently being executed, like “Sending email messages”.

start()#

Mark the task as having been started (as opposed to waiting for an available worker), and save it.

state#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

property state_text#

Get the translation into the current language of the current state of this status instance.

succeed()#

Mark the task as having finished successfully and save it.

task_class#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

task_id#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

total_steps#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

user#

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

user_id#
usertaskstatus_set#

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

uuid#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

user_tasks.rules module#

Sample implementation of authorization rules for the django-user-tasks permissions.

Requires use of the rules package. The rule implementations aren’t registered by default because that would interfere with the ability to use custom rules.) You can register them in another application’s rules.py:

import user_tasks

user_tasks.rules.add_rules()
user_tasks.rules.add_rules()#

Use the rules provided in this module to implement authorization checks for the django-user-tasks models.

These rules allow only superusers and the user who triggered a task to view its status or artifacts, cancel the task, or delete the status information and all its related artifacts. Only superusers are allowed to directly modify or delete an artifact (or to modify a task status record).

user_tasks.serializers module#

REST API serialization classes.

class user_tasks.serializers.ArtifactSerializer(*args, **kwargs)#

Bases: HyperlinkedModelSerializer

REST API serializer for the UserTaskArtifact model.

class Meta#

Bases: object

Artifact serializer settings.

extra_kwargs = {'status': {'lookup_field': 'uuid'}}#
fields = ('name', 'created', 'modified', 'status', 'file', 'text', 'url')#
model#

alias of UserTaskArtifact

get_file(obj)#

Get the URL of the artifact’s associated file data.

Arguments:

obj (UserTaskArtifact): The artifact being serialized

Returns:

six.text_type: The URL of the artifact’s file field (empty if there isn’t one)

class user_tasks.serializers.StatusSerializer(*args, **kwargs)#

Bases: HyperlinkedModelSerializer

REST API serializer for the UserTaskStatus model.

class Meta#

Bases: object

Status serializer settings.

fields = ('name', 'state', 'state_text', 'completed_steps', 'total_steps', 'attempts', 'created', 'modified', 'artifacts')#
model#

alias of UserTaskStatus

user_tasks.signals module#

Celery signal handlers and custom Django signal.

user_tasks.signals.create_user_task(sender=None, body=None, **kwargs)#

Create a UserTaskStatus record for each UserTaskMixin.

Also creates a UserTaskStatus for each chain, chord, or group containing the new UserTaskMixin.

user_tasks.signals.retrying_task(sender=None, **kwargs)#

Update the status record to reflect that a retry is pending.

user_tasks.signals.start_user_task(sender=None, **kwargs)#

Update the status record when execution of a UserTaskMixin begins.

user_tasks.signals.task_failed(sender=None, **kwargs)#

Update the status record accordingly when a UserTaskMixin fails.

user_tasks.signals.task_succeeded(sender=None, **kwargs)#

Update the status record accordingly when a UserTaskMixin finishes successfully.

user_tasks.tasks module#

Celery task abstract base classes.

class user_tasks.tasks.UserTask#

Bases: Task, UserTaskMixin

Abstract base class for user-triggered Celery tasks.

See UserTaskMixin for details on how to implement and use subclasses.

abstract = True#

Deprecated attribute abstract here for compatibility.

ignore_result = False#

If enabled the worker won’t store task state and return values for this task. Defaults to the :setting:`task_ignore_result` setting.

priority = None#

Default task priority.

rate_limit = None#

Rate limit for this task type. Examples: None (no rate limit), ‘100/s’ (hundred tasks a second), ‘100/m’ (hundred tasks a minute),`’100/h’` (hundred tasks an hour)

reject_on_worker_lost = None#

Even if acks_late is enabled, the worker will acknowledge tasks when the worker process executing them abruptly exits or is signaled (e.g., :sig:`KILL`/:sig:`INT`, etc).

Setting this to true allows the message to be re-queued instead, so that the task will execute again by the same worker, or another worker.

Warning: Enabling this can cause message loops; make sure you know what you’re doing.

request_stack = <celery.utils.threads._LocalStack object>#

Task request stack, the current request will be the topmost.

serializer = 'json'#

The name of a serializer that are registered with kombu.serialization.registry. Default is ‘json’.

store_errors_even_if_ignored = False#

When enabled errors will be stored even if the task is otherwise configured to ignore results.

track_started = False#

If enabled the task will report its status as ‘started’ when the task is executed by a worker. Disabled by default as the normal behavior is to not report that level of granularity. Tasks are either pending, finished, or waiting to be retried.

Having a ‘started’ status can be useful for when there are long running tasks and there’s a need to report what task is currently running.

The application default can be overridden using the :setting:`task_track_started` setting.

typing = True#

Enable argument checking. You can set this to false if you don’t want the signature to be checked when calling the task. Defaults to app.strict_typing.

class user_tasks.tasks.UserTaskMixin#

Bases: object

Mixin class for user-triggered Celery tasks.

Subclasses should usually override generate_name() and calculate_total_steps(). In order to access the status property (for calling its increment_completed_steps() and set_state() methods), task functions should generally be bound (bind=True in the task decorator) and have a self parameter.

Additionally, all task functions using a UserTaskMixin subclass must provide a user_id parameter, as either a positional or keyword argument.

classmethod arguments_as_dict(*args, **kwargs)#

Generate the arguments dictionary provided to generate_name() and calculate_total_steps().

This makes it possible to fetch arguments by name regardless of whether they were passed as positional or keyword arguments. Unnamed positional arguments are provided as a tuple under the key pos.

static calculate_total_steps(arguments_dict)#

Determine from the task’s parameters how many total steps the task will perform.

By default, there is only 1 step (the entire task); to allow for more useful progress bars in the UI, override this method to specify a meaningful larger number and call self.status.increment_completed_steps() periodically during task execution.

classmethod generate_name(arguments_dict)#

Generate a name for the corresponding UserTaskStatus model instance.

Should be implemented by each subclass to generate a meaningful name from the task parameters. Defaults to the name of the task function.

property status#

Get the UserTaskStatus model instance for this UserTaskMixin.

user_tasks.urls module#

URLs for user_tasks.

user_tasks.views module#

REST API endpoints.

class user_tasks.views.ArtifactViewSet(**kwargs)#

Bases: ReadOnlyModelViewSet

REST API endpoints for asynchronous task artifacts.

Artifact data can only be viewed or listed, not modified in any way via this API.

basename = None#
description = None#
detail = None#
filter_backends = (<class 'user_tasks.filters.ArtifactFilterBackend'>,)#
lookup_field = 'uuid'#
name = None#
permission_classes = (<class 'user_tasks.views.DjangoObjectPermissionsIncludingView'>,)#
queryset#
serializer_class#

alias of ArtifactSerializer

suffix = None#
class user_tasks.views.DjangoObjectPermissionsIncludingView#

Bases: DjangoObjectPermissions

Django REST Framework object permissions including <app>.view_<model>.

Yields better response codes than using the superclass directly, assuming you’ve defined a view_* permission for the models. The rationale for overriding perms_map is described in the Django REST framework documentation for permissions and filters.

perms_map = {'DELETE': ['%(app_label)s.delete_%(model_name)s'], 'GET': ['%(app_label)s.view_%(model_name)s'], 'HEAD': ['%(app_label)s.view_%(model_name)s'], 'OPTIONS': ['%(app_label)s.view_%(model_name)s'], 'PATCH': ['%(app_label)s.change_%(model_name)s'], 'POST': ['%(app_label)s.cancel_%(model_name)s'], 'PUT': ['%(app_label)s.change_%(model_name)s']}#
class user_tasks.views.StatusViewSet(**kwargs)#

Bases: DestroyModelMixin, ListModelMixin, RetrieveModelMixin, GenericViewSet

REST API endpoints for user-triggered asynchronous tasks.

The status of a task can be viewed, listed, deleted, or used to cancel the underlying task.

basename = None#
cancel(request, *args, **kwargs)#

Cancel the task associated with the specified status record.

Arguments:

request (Request): A POST including a task status record ID

Returns:

Response: A JSON response indicating whether the cancellation succeeded or not

description = None#
detail = None#
filter_backends = (<class 'user_tasks.filters.StatusFilterBackend'>,)#
lookup_field = 'uuid'#
name = None#
permission_classes = (<class 'user_tasks.views.DjangoObjectPermissionsIncludingView'>,)#
queryset#
serializer_class#

alias of StatusSerializer

suffix = None#

Module contents#

Management of user-triggered asynchronous tasks in Django projects.