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]
-
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
]
- 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:
ObjectNotFoundError – If no object is found.
MultipleObjectsFoundError – If multiple objects match the query.
NotImplementedError – If the method is not implemented by the subclass.
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:
- 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:
- 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:
- 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:
- 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:
- 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:
- 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:
- 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:
- 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")
- class paperap.models.abstract.queryset.BaseQuerySetProtocol(*args, **kwargs)[source]
-
-
resource:
BaseResource
[TypeVar
(_Model
, bound=BaseModel
), BaseQuerySet]
- __init__(*args, **kwargs)
-
resource:
- class paperap.models.abstract.queryset.StandardQuerySetProtocol(*args, **kwargs)[source]
Bases:
BaseQuerySetProtocol
,Protocol
,Generic
-
resource:
StandardResource
[TypeVar
(_Model
, bound=StandardModel
),Self
]
-
resource:
- 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:
- 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:
- 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)