paperap.models.abstract.queryset module

Provide query interfaces for interacting with Paperless-ngx API resources.

This module implements QuerySet classes that offer a Django-like interface for querying, filtering, and manipulating Paperless-ngx resources. The QuerySets are lazy-loaded and chainable, allowing for efficient API interactions.

class paperap.models.abstract.queryset.BaseQuerySet(resource, filters=None, _cache=None, _fetch_all=False, _next_url=None, _last_response=None, _iter=None, _urls_fetched=None)[source]

Bases: Iterable, Generic

A lazy-loaded, chainable query interface for Paperless-ngx resources.

Provides pagination, filtering, and caching functionality similar to Django’s QuerySet. Only fetches data when it’s actually needed, optimizing API requests and performance.

resource

The resource instance associated with the queryset.

filters

Dictionary of filters to apply to the API request.

_last_response

The last response received from the API.

_result_cache

List of model instances already fetched.

_fetch_all

Whether all results have been fetched.

_next_url

URL for the next page of results, if any.

_urls_fetched

List of URLs already fetched to prevent loops.

_iter

Current iterator over results, if any.

Examples

Basic usage:

>>> docs = client.documents()  # Returns a BaseQuerySet
>>> for doc in docs.filter(title__contains="invoice"):
...     print(doc.title)
Parameters:
  • resource (BaseResource[_Model, Self])

  • filters (dict[str, Any] | None)

  • _cache (list[_Model] | None)

  • _fetch_all (bool)

  • _next_url (str | None)

  • _last_response (ClientResponse)

  • _iter (Iterator[_Model] | None)

  • _urls_fetched (list[str] | None)

__init__(resource, filters=None, _cache=None, _fetch_all=False, _next_url=None, _last_response=None, _iter=None, _urls_fetched=None)[source]

Initialize a new BaseQuerySet.

Parameters:
  • resource (BaseResource[_Model, Self]) – The resource instance that will handle API requests.

  • filters (dict[str, Any] | None) – Initial filters to apply to the queryset.

  • _cache (list[_Model] | None) – Pre-populated result cache (internal use).

  • _fetch_all (bool) – Whether all results have been fetched (internal use).

  • _next_url (str | None) – URL for the next page of results (internal use).

  • _last_response (ClientResponse) – Last API response received (internal use).

  • _iter (Iterator[_Model] | None) – Current iterator over results (internal use).

  • _urls_fetched (list[str] | None) – List of URLs already fetched (internal use).

resource: BaseResource[TypeVar(_Model, bound= BaseModel), Self]
filters: dict[str, Any]
filter(**kwargs)[source]

Return a new QuerySet with the given filters applied.

Parameters:

**kwargs (Any) – Filters to apply, where keys are field names and values are desired values. Supports Django-style lookups like field__contains, field__in, etc.

Return type:

Self

Returns:

A new QuerySet with the additional filters applied.

Examples

Get documents with specific correspondent:

>>> docs = client.documents().filter(correspondent=1)

Filter with multiple conditions:

>>> docs = client.documents().filter(
...     title__contains="invoice",
...     created__gt="2023-01-01"
... )
exclude(**kwargs)[source]

Return a new QuerySet excluding objects with the given filters.

Parameters:

**kwargs (Any) – Filters to exclude, where keys are field names and values are excluded values. Supports the same lookup syntax as filter().

Return type:

Self

Returns:

A new QuerySet excluding objects that match the filters.

Examples

Get documents with any correspondent except ID 1:

>>> docs = client.documents().exclude(correspondent=1)

Exclude documents with specific words in title:

>>> docs = client.documents().exclude(title__contains="draft")
get(pk)[source]

Retrieve a single object from the API.

This base implementation raises NotImplementedError. Subclasses like StandardQuerySet implement this method for models with ID fields.

Parameters:

pk (Any) – The primary key (e.g., the id) of the object to retrieve.

Return type:

_Model

Returns:

A single object matching the query.

Raises:

Examples

Get document with ID 123:

>>> doc = client.documents().get(123)
count()[source]

Return the total number of objects in the queryset.

Makes an API request if necessary to determine the total count of objects matching the current filters.

Return type:

int

Returns:

The total count of objects matching the filters.

Raises:

NotImplementedError – If the count cannot be determined from the API response.

Examples

Count all documents:

>>> total = client.documents().count()
>>> print(f"Total documents: {total}")

Count filtered documents:

>>> invoice_count = client.documents().filter(title__contains="invoice").count()
count_this_page()[source]

Return the number of objects on the current page.

Counts only the objects on the current page of results, without fetching additional pages. Useful for pagination displays.

Return type:

int

Returns:

The count of objects on the current page.

Raises:

NotImplementedError – If the current page count cannot be determined.

Examples

Get count of current page:

>>> page_count = client.documents().count_this_page()
>>> print(f"Items on this page: {page_count}")
all()[source]

Return a new QuerySet that copies the current one.

Creates a copy of the current queryset with the same filters. Often used to create a new queryset instance for method chaining.

Return type:

Self

Returns:

A copy of the current QuerySet.

Examples

Create a copy of a queryset:

>>> all_docs = client.documents().all()

Chain with other methods:

>>> recent_docs = client.documents().all().order_by('-created')
order_by(*fields)[source]

Return a new QuerySet ordered by the specified fields.

Parameters:

*fields (str) – Field names to order by. Prefix with ‘-’ for descending order. Multiple fields can be specified for multi-level sorting.

Return type:

Self

Returns:

A new QuerySet with the ordering applied.

Examples

Order documents by title ascending:

>>> docs = client.documents().order_by('title')

Order by multiple fields (created date descending, then title ascending):

>>> docs = client.documents().order_by('-created', 'title')
first()[source]

Return the first object in the QuerySet, or None if empty.

Optimizes the API request by limiting to a single result when possible.

Return type:

_Model | None

Returns:

The first object or None if no objects match.

Examples

Get the first document:

>>> first_doc = client.documents().first()
>>> if first_doc:
...     print(f"First document: {first_doc.title}")

Get the first document matching a filter:

>>> first_invoice = client.documents().filter(title__contains="invoice").first()
last()[source]

Return the last object in the QuerySet, or None if empty.

Note

This method requires fetching all results to determine the last one, which may be inefficient for large result sets.

Return type:

_Model | None

Returns:

The last object or None if no objects match.

Examples

Get the last document:

>>> last_doc = client.documents().last()
>>> if last_doc:
...     print(f"Last document: {last_doc.title}")

Get the last document in a specific order:

>>> oldest_doc = client.documents().order_by('created').last()
exists()[source]

Return True if the QuerySet contains any results.

Optimizes the API request by checking for at least one result rather than fetching all results.

Return type:

bool

Returns:

True if there are any objects matching the filters.

Examples

Check if any documents exist:

>>> if client.documents().exists():
...     print("Documents found")

Check if specific documents exist:

>>> has_invoices = client.documents().filter(title__contains="invoice").exists()
none()[source]

Return an empty QuerySet.

Creates a queryset that will always return no results, which is useful for conditional queries.

Return type:

Self

Returns:

An empty QuerySet.

Examples

Create an empty queryset:

>>> empty_docs = client.documents().none()
>>> len(empty_docs)
0

Conditional query:

>>> if condition:
...     docs = client.documents().filter(title__contains="invoice")
... else:
...     docs = client.documents().none()
filter_field_by_str(field, value, *, exact=True, case_insensitive=True)[source]

Filter a queryset based on a given string field.

Allows subclasses to easily implement custom filter methods for string fields with consistent behavior.

Parameters:
  • field (str) – The field name to filter by.

  • value (str) – The string value to filter against.

  • exact (bool) – Whether to filter by an exact match (True) or contains (False).

  • case_insensitive (bool) – Whether the filter should be case-insensitive.

Return type:

Self

Returns:

A new QuerySet instance with the filter applied.

Examples

Filter documents by title (case-insensitive exact match):

>>> docs = client.documents().filter_field_by_str('title', 'Invoice', exact=True)

Filter documents by title containing text (case-insensitive):

>>> docs = client.documents().filter_field_by_str('title', 'invoice', exact=False)
__iter__()[source]

Iterate over the objects in the QuerySet.

Implements lazy loading of results, fetching additional pages as needed when iterating through the queryset.

Return type:

Iterator[_Model]

Returns:

An iterator over the model instances.

Examples

Iterate through documents:

>>> for doc in client.documents():
...     print(doc.title)
__len__()[source]

Return the number of objects in the QuerySet.

Calls count() to determine the total number of objects matching the current filters.

Return type:

int

Returns:

The count of objects.

Examples

Get the number of documents:

>>> num_docs = len(client.documents())
>>> print(f"Total documents: {num_docs}")
__bool__()[source]

Return True if the QuerySet has any results.

Calls exists() to check if any objects match the current filters.

Return type:

bool

Returns:

True if there are any objects matching the filters.

Examples

Check if any documents exist:

>>> if client.documents():
...     print("Documents found")
__getitem__(key)[source]

Retrieve an item or slice of items from the QuerySet.

Supports both integer indexing and slicing, optimizing API requests when possible by using limit and offset parameters.

Parameters:

key (int | slice) – An integer index or slice object.

Return type:

_Model | list[_Model]

Returns:

A single object or list of objects.

Raises:

IndexError – If the index is out of range.

Examples

Get a single document by position:

>>> first_doc = client.documents()[0]

Get a slice of documents:

>>> recent_docs = client.documents().order_by('-created')[:10]
__contains__(item)[source]

Return True if the QuerySet contains the given object.

Checks if the given object is present in the queryset by comparing it with each object in the queryset.

Parameters:

item (Any) – The object to check for.

Return type:

bool

Returns:

True if the object is in the QuerySet.

Examples

Check if a document is in a queryset:

>>> doc = client.documents().get(123)
>>> if doc in client.documents().filter(title__contains="invoice"):
...     print("Document is an invoice")
class paperap.models.abstract.queryset.StandardQuerySet(resource, filters=None, _cache=None, _fetch_all=False, _next_url=None, _last_response=None, _iter=None, _urls_fetched=None)[source]

Bases: BaseQuerySet, Generic

A queryset for StandardModel instances with ID fields.

Extends BaseQuerySet to provide additional functionality specific to models with standard fields like ‘id’, including direct lookups by ID, bulk operations, and specialized filtering methods.

resource

The StandardResource instance associated with the queryset.

Examples

Get documents by ID:

>>> doc = client.documents().get(123)

Filter documents by ID:

>>> docs = client.documents().id([1, 2, 3])

Perform bulk operations:

>>> client.documents().filter(title__contains="draft").delete()
Parameters:
  • resource (BaseResource[_Model, Self])

  • filters (dict[str, Any] | None)

  • _cache (list[_Model] | None)

  • _fetch_all (bool)

  • _next_url (str | None)

  • _last_response (ClientResponse)

  • _iter (Iterator[_Model] | None)

  • _urls_fetched (list[str] | None)

resource: StandardResource[TypeVar(_Model, bound= StandardModel), Self]
get(pk)[source]

Retrieve a single object from the API by its ID.

First checks the result cache for an object with the given ID, then falls back to making a direct API request if not found.

Parameters:

pk (int) – The ID of the object to retrieve.

Return type:

_Model

Returns:

A single object matching the ID.

Raises:

ObjectNotFoundError – If no object with the given ID exists.

Examples

Get document with ID 123:

>>> doc = client.documents().get(123)
>>> print(f"Retrieved: {doc.title}")
id(value)[source]

Filter models by ID.

Provides a convenient way to filter objects by their ID or a list of IDs.

Parameters:

value (int | list[int]) – The ID or list of IDs to filter by.

Return type:

Self

Returns:

Filtered QuerySet containing only objects with the specified ID(s).

Examples

Get document with ID 123:

>>> doc = client.documents().id(123).first()

Get multiple documents by ID:

>>> docs = client.documents().id([123, 456, 789])
>>> for doc in docs:
...     print(doc.title)
__contains__(item)[source]

Return True if the QuerySet contains the given object.

Checks if an object with the same ID is in the queryset. Can accept either a model instance or an integer ID.

Note

This method only ensures a match by ID, not by full object equality. This is intentional, as the object may be outdated or not fully populated.

Parameters:

item (Any) – The object or ID to check for.

Return type:

bool

Returns:

True if an object with the matching ID is in the QuerySet.

Examples

Check if a document is in a queryset:

>>> doc = client.documents().get(123)
>>> if doc in client.documents().filter(title__contains="invoice"):
...     print("Document is an invoice")

Check if a document ID is in a queryset:

>>> if 123 in client.documents().filter(title__contains="invoice"):
...     print("Document 123 is an invoice")
filters: dict[str, Any]
class paperap.models.abstract.queryset.BaseQuerySetProtocol(*args, **kwargs)[source]

Bases: Protocol, Generic

resource: BaseResource[TypeVar(_Model, bound= BaseModel), BaseQuerySet]
filters: dict[str, Any]
filter(**kwargs)[source]
Parameters:

kwargs (Any)

Return type:

Self

exclude(**kwargs)[source]
Parameters:

kwargs (Any)

Return type:

Self

all()[source]
Return type:

Self

order_by(*fields)[source]
Parameters:

fields (str)

Return type:

Self

first()[source]
Return type:

_Model | None

last()[source]
Return type:

_Model | None

exists()[source]
Return type:

bool

none()[source]
Return type:

Self

filter_field_by_str(field, value, *, exact=True, case_insensitive=True)[source]
Parameters:
Return type:

Self

count()[source]
Return type:

int

count_this_page()[source]
Return type:

int

__init__(*args, **kwargs)
class paperap.models.abstract.queryset.StandardQuerySetProtocol(*args, **kwargs)[source]

Bases: BaseQuerySetProtocol, Protocol, Generic

resource: StandardResource[TypeVar(_Model, bound= StandardModel), Self]
get(pk)[source]
Parameters:

pk (int)

Return type:

_Model

id(value)[source]
Parameters:

value (int | list[int])

Return type:

Self

class paperap.models.abstract.queryset.SupportsBulkActions(*args, **kwargs)[source]

Bases: StandardQuerySetProtocol, Protocol

bulk_action(action, **kwargs)[source]

Perform a bulk action on all objects in the queryset.

Fetches all IDs in the queryset and passes them to the resource’s bulk_action method, allowing operations to be performed on multiple objects in a single API request.

Parameters:
  • action (str) – The action to perform (e.g., “delete”, “merge”).

  • **kwargs (Any) – Additional parameters for the action.

Return type:

TypeAliasType

Returns:

The API response containing results of the bulk action.

Raises:

NotImplementedError – If the resource doesn’t support bulk actions.

Examples

Delete all documents with “draft” in the title:

>>> client.documents().filter(title__contains="draft").bulk_action("delete")

Merge documents with custom parameters:

>>> client.documents().filter(correspondent_id=5).bulk_action(
...     "merge",
...     metadata_document_id=123
... )
delete()[source]

Delete all objects in the queryset.

This is a convenience method that calls bulk_action(“delete”).

Return type:

TypeAliasType

Returns:

The API response containing results of the delete operation.

Examples

Delete all documents with “draft” in the title:

>>> client.documents().filter(title__contains="draft").delete()

Delete old documents:

>>> from datetime import datetime, timedelta
>>> one_year_ago = (datetime.now() - timedelta(days=365)).isoformat()
>>> client.documents().filter(created__lt=one_year_ago).delete()
bulk_update(**kwargs)[source]

Update all objects in the queryset with the given values.

Allows updating multiple objects with the same field values in a single API request.

Parameters:

**kwargs (Any) – Fields to update and their new values.

Return type:

TypeAliasType

Returns:

The API response containing results of the update operation.

Raises:

NotImplementedError – If the resource doesn’t support bulk updates.

Examples

Update the correspondent for all documents with “invoice” in the title:

>>> client.documents().filter(title__contains="invoice").bulk_update(
...     correspondent=5,
...     document_type=3
... )
bulk_assign_tags(tag_ids, remove_existing=False)[source]

Assign tags to all objects in the queryset.

Adds the specified tags to all objects in the queryset.

Parameters:
  • tag_ids (list[int]) – List of tag IDs to assign.

  • remove_existing (bool) – If True, remove existing tags before assigning new ones. If False (default), add the new tags to any existing tags.

Return type:

TypeAliasType

Returns:

The API response containing results of the operation.

Raises:

NotImplementedError – If the resource doesn’t support bulk tag assignment.

Examples

Add tags to all invoices:

>>> client.documents().filter(title__contains="invoice").bulk_assign_tags([1, 2])

Replace all tags on tax documents:

>>> client.documents().filter(title__contains="tax").bulk_assign_tags(
...     [5, 6],
...     remove_existing=True
... )
bulk_assign_correspondent(correspondent_id)[source]

Assign a correspondent to all objects in the queryset.

Sets the correspondent for all objects in the queryset to the specified correspondent ID.

Parameters:

correspondent_id (int) – Correspondent ID to assign.

Return type:

TypeAliasType

Returns:

The API response containing results of the operation.

Raises:

NotImplementedError – If the resource doesn’t support bulk correspondent assignment.

Examples

Set correspondent for all invoices:

>>> client.documents().filter(title__contains="invoice").bulk_assign_correspondent(5)
bulk_assign_document_type(document_type_id)[source]

Assign a document type to all objects in the queryset.

Sets the document type for all objects in the queryset to the specified document type ID.

Parameters:

document_type_id (int) – Document type ID to assign.

Return type:

TypeAliasType

Returns:

The API response containing results of the operation.

Raises:

NotImplementedError – If the resource doesn’t support bulk document type assignment.

Examples

Set document type for all invoices:

>>> client.documents().filter(title__contains="invoice").bulk_assign_document_type(3)
bulk_assign_storage_path(storage_path_id)[source]

Assign a storage path to all objects in the queryset.

Sets the storage path for all objects in the queryset to the specified storage path ID.

Parameters:

storage_path_id (int) – Storage path ID to assign.

Return type:

TypeAliasType

Returns:

The API response containing results of the operation.

Raises:

NotImplementedError – If the resource doesn’t support bulk storage path assignment.

Examples

Set storage path for all tax documents:

>>> client.documents().filter(title__contains="tax").bulk_assign_storage_path(2)
bulk_assign_owner(owner_id)[source]

Assign an owner to all objects in the queryset.

Sets the owner for all objects in the queryset to the specified owner ID.

Parameters:

owner_id (int) – Owner ID to assign.

Return type:

TypeAliasType

Returns:

The API response containing results of the operation.

Raises:

NotImplementedError – If the resource doesn’t support bulk owner assignment.

Examples

Set owner for all personal documents:

>>> client.documents().filter(title__contains="personal").bulk_assign_owner(1)