PluginDataBase Model

class smarter.apps.plugin.models.PluginDataBase(*args, **kwargs)[source]

Bases: TimestampedModel, SmarterHelperMixin

Abstract base class for all plugin data configuration models in the Smarter platform.

PluginDataBase defines the common interface and fields required for storing and validating plugin data specifications, including parameter schemas, test values, and descriptive metadata. It is not intended to be instantiated directly, but rather to be subclassed by concrete data models such as PluginDataStatic, PluginDataSql, and PluginDataApi, each of which implements data handling for a specific plugin type (static, SQL, or API).

This base class enforces a consistent structure for plugin data models by providing:
  • A reference to the associated PluginMeta instance, linking data configuration to plugin metadata.

  • A description field for documenting the data returned by the plugin.

  • A parameters field for specifying the expected input schema, validated against OpenAI-compatible conventions.

  • A test_values field for storing example parameter values used in validation and testing.

  • Abstract methods for returning sanitized data and the plugin’s data payload, which must be implemented by subclasses.

  • Validation methods to ensure that all parameters are covered by test values and that test values conform to the expected structure.

Subclasses are responsible for implementing the logic to return data in the appropriate format for their plugin type, as well as any additional validation or preparation steps required for their data source (e.g., SQL query, API request, or static data).

This class is foundational for the plugin data architecture, ensuring that all plugin data models in the Smarter system adhere to a uniform interface and validation strategy.

See also:

Parameters:
  • id (BigAutoField) – Primary key: ID

  • created_at (DateTimeField) – Created at

  • updated_at (DateTimeField) – Updated at

  • description (TextField) – Description. A brief description of what this plugin returns. Be verbose, but not too verbose.

  • parameters (JSONField) –

    Parameters. A JSON dict containing parameter names and data types. Example: {‘required’: [], ‘properties’: {‘max_cost’: {‘type’: ‘float’, ‘description’: ‘the maximum cost that a student is willing to pay for a course.’}, ‘description’: {‘enum’: [‘AI’, ‘mobile’, ‘web’, ‘database’, ‘network’, ‘neural networks’], ‘type’: ‘string’, ‘description’: ‘areas of specialization for courses in the catalogue.’}}}

    A JSON dict containing parameter names and data types. Example: {‘required’: [], ‘properties’: {‘max_cost’: {‘type’: ‘float’, ‘description’: ‘the maximum cost that a student is willing to pay for a course.’}, ‘description’: {‘enum’: [‘AI’, ‘mobile’, ‘web’, ‘database’, ‘network’, ‘neural networks’], ‘type’: ‘string’, ‘description’: ‘areas of specialization for courses in the catalogue.’}}}

  • test_values (JSONField) –

    Test values. A JSON dict containing test values for each parameter. Example: {‘city’: ‘San Francisco’}

    A JSON dict containing test values for each parameter. Example: {‘city’: ‘San Francisco’}

Relationship fields:

Parameters:

plugin (OneToOneField to PluginMeta) – Plugin (related name: plugin_data_base_plugin)

Reverse relationships:

Parameters:
exception DoesNotExist

Bases: ObjectDoesNotExist

__init__(*args, **kwargs)
add_note(object, /)

Exception.add_note(note) – add a note to the exception

args
silent_variable_failure = True
with_traceback(object, /)

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

HASH_FLOOR = 1000000
HASH_PREFIX = 'r'
HASH_SUFFIX = 'x'
exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

__init__(*args, **kwargs)
add_note(object, /)

Exception.add_note(note) – add a note to the exception

args
with_traceback(object, /)

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

__init__(*args, **kwargs)
async adelete(using=None, keep_parents=False)
property amnesty_urls: list[str]

Returns a list of URLs that are exempt from certain checks.

This is a placeholder and should be overridden in subclasses.

Returns:

List of URL path strings that are exempt.

Return type:

list[str]

async arefresh_from_db(using=None, fields=None, from_queryset=None)
async asave(*args, force_insert=False, force_update=False, using=None, update_fields=None)
cache_expiration = 60
classmethod check(**kwargs)
clean()

Hook for doing any extra model-wide validation after clean() has been called on every field by self.clean_fields. Any ValidationError raised by this method will not be associated with a particular field; it will have a special-case association with the field defined by NON_FIELD_ERRORS.

clean_fields(exclude=None)

Clean all fields and raise a ValidationError containing a dict of all validation errors if any occur.

created_at

DateTimeField

Created at

Timestamp indicating when the model instance was created. This field is automatically set to the current date and time when the instance is first created. It is indexed in the database for efficient querying.

Type:

Type

abstractmethod data(params=None)[source]

Returns a dict of custom data return results.

Return type:

dict

data_to_dict(data)

Converts data to a dictionary, handling different types of input.

This method accepts either a dictionary or a string. If a string is provided, it will attempt to parse it as JSON first, and if that fails, as YAML. If parsing fails or the data type is unsupported, a SmarterValueError is raised.

Parameters:

data (dict or str) – The data to convert, either a dict or a JSON/YAML string.

Returns:

The data as a dictionary.

Return type:

dict

Raises:

SmarterValueError – If the data cannot be converted to a dictionary.

date_error_message(lookup_type, field_name, unique_for)
delete(using=None, keep_parents=False)
description

TextField

Description. A brief description of what this plugin returns. Be verbose, but not too verbose.

Type:

Type

property elapsed_updated: int | None

Calculate the absolute time difference in seconds between a given datetime and the model’s updated_at timestamp.

This property is useful for determining how much time has elapsed since the model instance was last updated, or for comparing the updated_at field to any arbitrary datetime.

Parameters:

  • dt (datetime, optional): The reference datetime to compare against updated_at. - If dt is not provided, the current time is used. - Both naive and timezone-aware datetime objects are supported; the method will handle conversions as needed.

Returns:

  • int or None: The absolute difference in seconds between updated_at and dt. Returns None if updated_at is not set.

Example Usage:

obj = MyModel.objects.get(pk=1)
# Time since last update
seconds = obj.elapsed_updated
print(f"Seconds since last update: {seconds}")

# Compare to a specific datetime
import datetime
dt = datetime.datetime(2025, 12, 1, 12, 0, 0)
diff = obj.elapsed_updated(dt)
print(f"Seconds between updated_at and 2025-12-01 12:00:00: {diff}")

Note

  • Handles both naive and aware datetime objects, converting as necessary to ensure accurate calculation.

  • If updated_at is not set (e.g., the object has not been saved), returns None.

Attention

  • If dt is provided and is not a datetime.datetime instance, a TypeError will be raised.

  • Always ensure that updated_at is set before relying on this property for calculations.

classmethod find_hash(value)

Finds and returns the first substring in the given value that matches the hashed ID format.

Parameters:

value (str) – The string to search for a hashed ID.

Returns:

The first matching hashed ID if found, otherwise None.

Return type:

Optional[str]

property formatted_class_name: str

Returns the class name formatted for logging.

Returns:

The formatted class name as a string.

Return type:

str

property formatted_state_not_ready: str

Returns the not-ready state formatted for logging.

Returns:

The formatted not-ready state as a string.

Return type:

str

property formatted_state_ready: str

Returns the readiness state formatted for logging.

Returns:

The formatted readiness state as a string.

Return type:

str

classmethod from_db(db, field_names, values)
full_clean(exclude=None, validate_unique=True, validate_constraints=True)

Call clean_fields(), clean(), validate_unique(), and validate_constraints() on the model. Raise a ValidationError for any errors that occur.

classmethod get_cached_data_by_plugin(plugin, invalidate=False)[source]
Return type:

Optional[PluginDataBase]

classmethod get_cached_object(invalidate=False, pk=None)

Retrieve a model instance by primary key, using caching to optimize performance. This method is selectively overridden in models that inherit from TimestampedModel to provide class-specific function parameters.

Example usage:

# Retrieve by primary key
instance = MyModel.get_cached_object(pk=1)
Parameters:
  • invalidate (bool, optional) – Whether to invalidate the cache for this retrieval.

  • pk (int, optional) – The primary key of the model instance to retrieve.

Returns:

The model instance if found, otherwise None.

Return type:

Optional[models.Model]

classmethod get_cached_objects(invalidate=False)

Retrieve model instances using caching to optimize performance. This method is selectively overridden in models that inherit from TimestampedModel to provide class-specific function parameters.

Example usage:

# Retrieve all instances
instances = MyModel.get_cached_objects()
Parameters:

invalidate (bool) – Whether to invalidate the cache for this retrieval.

Returns:

A queryset of all model instances.

Return type:

QuerySet

get_constraints()
get_deferred_fields()

Return a set containing names of deferred fields for this instance.

classmethod get_object_by_locator(locator)

Retrieves an object based on its record locator.

Example:

obj = MyModel.objects.create()
print(obj.id)  # e.g., 123
locator = obj.record_locator # e.g., "mymodel-rc2x"

retrieved_obj = MyModel.get_object_by_locator(locator)
print(type(retrieved_obj))  # Should be <class 'MyModel'>
print(retrieved_obj)  # Should be the same as obj
Parameters:

locator (str) – The record locator string to decode and search for.

Returns:

The model instance if found, otherwise None.

Return type:

Optional[TimestampedModel]

classmethod hash_regex()

Returns a regex pattern that matches the hashed ID format for this model anywhere in a string.

The hashed ID format is defined by the HASH_PREFIX and HASH_SUFFIX class attributes, with a base64-encoded string in between. This regex can be used to validate or extract hashed IDs from strings, including when embedded in URLs.

Returns:

A regex pattern for matching hashed IDs.

Return type:

re.Pattern

property hashed_id: str

Returns a URL-friendly hashed version of the object’s ID for use in URLs and other contexts where an obscured, non-identifying, non-sequential identifier is preferred.

Encoding scheme: 1. Take the object’s ID and add a large constant (HASH_FLOOR) to ensure it’s not easily guessable. 2. Convert the resulting number to a string and encode it using URL-safe base64 encoding. 3. Remove any padding characters from the encoded string. 4. Add a prefix and suffix to the encoded string to create a recognizable format.

Example:

obj = MyModel.objects.create()
print(obj.id)  # e.g., 123
print(obj.hashed_id)  # e.g., "rc2x"
Returns:

Hashed ID string (URL-safe, no padding)

Return type:

str

id

BigAutoField

Primary key: ID

Type:

Type

classmethod id_from_hashed_id(hashed_id)

Decodes a hashed ID back to the original object ID.

decoding scheme: 1. Validate that the hashed ID starts with the expected prefix and ends with the expected suffix. 2. Remove the prefix and suffix to isolate the base64-encoded string. 3. Add padding if necessary to make the length of the encoded string a multiple of 4. 4. Decode the base64 string to get the original number as a string. 5. Convert the decoded string to an integer and subtract the HASH_FLOOR to get the original ID.

Example:

my_record = MyModel.objects.create()
print(my_record.id)  # e.g., 123
hashed_id = my_record.hashed_id  # e.g., "rc2x"

original_id = MyModel.id_from_hashed_id(hashed_id)
print(original_id)  # Should print the original ID (e.g., 123)
Parameters:

hashed_id (str) – The hashed ID string to decode (URL-safe, no padding).

Returns:

The original object ID if decoding is successful, otherwise None.

Return type:

Optional[int]

mask_string(string='', mask_char='*', mask_length=4, string_length=8)

Masks a string for secure logging.

This utility function masks all but the last unmasked_chars characters of the input string, replacing them with asterisks. It is useful for logging sensitive information like API keys or passwords.

Parameters:
  • string (str) – The string to be masked.

  • mask_char (str) – The character used for masking.

  • mask_length (int) – The number of characters to mask.

  • string_length (int) – The length of the string to consider for masking.

Returns:

The masked string.

Return type:

str

objects = <django.db.models.Manager object>
parameters

JSONField

Parameters. A JSON dict containing parameter names and data types. Example: {‘required’: [], ‘properties’: {‘max_cost’: {‘type’: ‘float’, ‘description’: ‘the maximum cost that a student is willing to pay for a course.’}, ‘description’: {‘enum’: [‘AI’, ‘mobile’, ‘web’, ‘database’, ‘network’, ‘neural networks’], ‘type’: ‘string’, ‘description’: ‘areas of specialization for courses in the catalogue.’}}}

A JSON dict containing parameter names and data types. Example: {‘required’: [], ‘properties’: {‘max_cost’: {‘type’: ‘float’, ‘description’: ‘the maximum cost that a student is willing to pay for a course.’}, ‘description’: {‘enum’: [‘AI’, ‘mobile’, ‘web’, ‘database’, ‘network’, ‘neural networks’], ‘type’: ‘string’, ‘description’: ‘areas of specialization for courses in the catalogue.’}}}

Type:

Type

property pk
plugin

OneToOneField to PluginMeta

Plugin (related name: plugin_data_base_plugin)

Type:

Type

plugin_id

Internal field, use plugin instead.

plugindataapi

Reverse OneToOneField from PluginDataApi

The plugin data api of this plugin data base (related name of plugindatabase_ptr)

Type:

Type

plugindatasql

Reverse OneToOneField from PluginDataSql

The plugin data sql of this plugin data base (related name of plugindatabase_ptr)

Type:

Type

plugindatastatic

Reverse OneToOneField from PluginDataStatic

The Plugin Static Data of this plugin data base (related name of plugindatabase_ptr)

Type:

Type

prepare_database_save(field)
property ready: bool

Indicates whether the object is ready for use. This is a placeholder that should be overridden in subclasses.

Returns:

True if ready, False otherwise.

Return type:

bool

property record_locator: str

Returns a short, URL-friendly record locator derived from the object’s ID.

Example:

obj = MyModel.objects.create(name="Example")
print(obj.id)  # e.g., 123
print(obj.record_locator)  # e.g., "chatbot-rc2x"
Returns:

Record locator string (URL-safe, no padding)

Return type:

str

refresh_from_db(using=None, fields=None, from_queryset=None)

Reload field values from the database.

By default, the reloading happens from the database this instance was loaded from, or by the read router if this instance wasn’t loaded from any database. The using parameter will override the default.

Fields can be used to specify which fields to reload. The fields should be an iterable of field attnames. If fields is None, then all non-deferred fields are reloaded.

When accessing deferred fields of an instance, the deferred loading of the field will call this method.

abstractmethod sanitized_return_data(params=None)[source]

Returns a dict of custom data return results.

Return type:

dict

save(*args, **kwargs)[source]

Override the save method to validate the field dicts.

save_base(raw=False, force_insert=False, force_update=False, using=None, update_fields=None)

Handle the parts of saving which should be done only once per save, yet need to be done in raw saves, too. This includes some sanity checks and signal sending.

The ‘raw’ argument is telling save_base not to save any parent models and not to do any changes to the values before save. This is used by fixture loading.

serializable_value(field_name)

Return the value of the field name for this instance. If the field is a foreign key, return the id value instead of the object. If there’s no Field object with this name on the model, return the model attribute’s value.

Used to serialize a field’s value (in the serializer, or form output, for example). Normally, you would just access the attribute directly and not use this method.

smarter_build_absolute_uri(request)

Attempts to get the absolute URI from a request object.

This utility function tries to retrieve the request URL from any valid child class of django.http.HttpRequest. It is especially useful in unit tests or scenarios where the request object may not implement build_absolute_uri().

Parameters:

request (Optional[HttpRequest]) – The request object.

Returns:

The absolute request URL.

Return type:

Optional[str]

Raises:

SmarterValueError – If the URI cannot be built from the request.

sorted_dict(data)

Returns a new dictionary with keys sorted.

Parameters:

data (dict) – The dictionary to sort.

Returns:

A new dictionary with sorted keys.

Return type:

dict

test_values

JSONField

Test values. A JSON dict containing test values for each parameter. Example: {‘city’: ‘San Francisco’}

A JSON dict containing test values for each parameter. Example: {‘city’: ‘San Francisco’}

Type:

Type

to_json()

Serialize the model instance to a JSON-compatible dictionary.

This method uses the custom SmarterJSONEncoder to ensure that all fields, including timestamps and any complex data types, are properly serialized.

Returns:

A dictionary representation of the model instance suitable for JSON serialization.

Return type:

dict[str, Any]

property unformatted_class_name: str

Returns the raw class name without formatting.

Returns:

The unformatted class name as a string.

Return type:

str

This is useful for logging or serialization where the plain class name is needed.

unique_error_message(model_class, unique_check)
updated_at

DateTimeField

Updated at

Timestamp indicating when the model instance was last updated. This field is automatically updated to the current date and time whenever the instance is saved. It is indexed in the database for efficient querying.

Type:

Type

validate()

Validate the model.

Attention

Intended to be overridden in subclasses to provide custom validation logic.

validate_all_parameters_in_test_values()[source]

Ensure that every parameter defined in parameters['properties'] has a corresponding entry in test_values.

This method checks that all parameter names specified in the parameters field are present in the test_values list. Each test value should be a dictionary with a name key matching a parameter name.

Example:

parameters = {
    "properties": {
        "description": {"type": "string"},
        "max_cost": {"type": "float"}
    }
}
test_values = [
    {"name": "description", "value": "AI"},
    {"name": "max_cost", "value": "500.0"}
]

If any parameter is missing from test_values, a SmarterValueError is raised.

Raises:

SmarterValueError – If a parameter is defined in parameters but not present in test_values.

Return type:

None

validate_constraints(exclude=None)
validate_unique(exclude=None)

Check unique constraints on the model and raise ValidationError if any failed.