.. auto generated by export_components.py ******** Database ******** |development| |area| A plethora, a cornucopia, a totally ridiculous number of models, fields, and other resources that may be used as a starting point for your database. **Version:** 0.4.0-d .. include:: _includes/db.rst The resources provided by SuperDjango DB general consist of abstract models that may be used for various common (and some not so common) purposes. .. note:: SuperDjango DB does *not* (and will never) provide concrete models. .. _db-db-archived: Archived Models =============== |development| |library| **Version:** 0.10.0-d Provides support for a simple archive workflow. Developer Reference: :ref:`db-db-archived-developer` **Provides** - `Admin `_ : base - `Managers `_ - `Models `_ : abstract Usage ----- .. code-block:: python from superdjango.db.archived.managers import ArchivedManager from superdjango.db.archived.models import ArchivedByModel class StrategicPlan(ArchivedByModel): objects = ArchivedManager() archived_plans = StrategicPlan.objects.archived() unarchived_plans = StrategicPlan.objects.unarchived() .. _db-db-audit: Audit Models ============ |development| |library| **Version:** 0.11.0-d Adds support for added by/modified by/viewed by (and added/modified/viewed date/time) to a model. Developer Reference: :ref:`db-db-audit-developer` **Provides** - `Admin `_ : base, filters - `Models `_ : fields, abstract, mixins - Utilities .. _db-db-calculated: Calculated Fields ================= |planning| |library| **Version:** 0.6.0-p Provides support for standard calculated fields as well as creating your own calculated fields. Developer Reference: :ref:`db-db-calculated-developer` **Provides** - `Models `_ : field mixins, fields Abstract -------- Calculated fields can be useful when aggregating data or connecting (concatenating) strings. This library provides various fields for use in automatic calculation on save. .. _db-db-completed: Completed Models ================ |development| |library| **Version:** 0.11.0-d Provides the ability to mark a record as complete. Developer Reference: :ref:`db-db-completed-developer` **Provides** - `Admin `_ : base - `Managers `_ - `Models `_ : abstract Abstract -------- A completion workflow is often needed for tasks, projects, and other common types of web application records. This library provides support for such a workflow. Usage ----- .. code-block:: python from superdjango.db.completed.managers import CompletedManager from superdjango.db.completed.models import CompletedByModel class Task(CompletedByModel): objects = CompletedManager() completed_tasks = Task.objects.complete() incomplete_tasks = Task.objects.incomplete() .. _db-db-datetime: Date/Time Models ================ |development| |library| **Version:** 0.8.0-d Fields and abstract models for working with dates and datetimes. Developer Reference: :ref:`db-db-datetime-developer` **Provides** - `Models `_ : fields, abstract .. _db-db-default: Default Models ============== |experimental| |library| **Version:** 0.6.0-x Provides the ability to mark a record as the default of it's type. Developer Reference: :ref:`db-db-default-developer` **Provides** - `Admin `_ : base - `Managers `_ - `Models `_ : abstract, mixins Abstract -------- Records that are identified as "the default" are useful for establishing intelligent defaults for things like configuration options and lookup (validation) data. Usage ----- Support you have an ``AddressType`` lookup and that only one address type may be the default for new records that refer to address type. .. code-block:: python # myapp/models.py from django.db import models from superdjango.db.default.managers import DefaultManager from superdjango.db.default.models import DefaultModel from superdjango.db.lookups.models import StringLookupModel from django.db.models.signals import pre_save class AddressType(DefaultModel, StringLookupModel): objects = DefaultManager() # ... Set the required receiver: .. code-block:: python # myapp/receivers.py from .models import AddressType pre_save.connect( AddressType.allow_one_default, AddressType, dispatch_uid="addresstype_allow_one_default" ) To require that a default address type always exists, use the ``require_one_default`` instead: .. code-block:: python # Or to require a default record. pre_save.connect( AddressType.require_one_default, AddressType, dispatch_uid="addresstype_require_one_default" ) Load receivers in your ``apps.py`` file: .. code-block:: python from django.apps import AppConfig class DefaultConfig(AppConfig): name = 'myapp' label = 'myapp' def ready(self): from . import receivers To implement the default in a form: .. code-block:: python from django import forms class EmployeeAddress(forms.ModelForm): class Meta: model = EmployeeAddress fields = [ "address_type", # ... ] def __init__(*args, **kwargs): super(EmployeeForm, self).__init__(*args, **kwargs) self.fields['address_type'].initial = AddressType.objects.default() .. _db-db-displayed: Displayed Models ================ |alpha| |library| **Version:** 0.4.0-a Provides a consistent means of acquiring the human friendly name of a model instance. Developer Reference: :ref:`db-db-displayed-developer` **Provides** - `Models `_ : abstract, mixins Abstract -------- What is a *display name*? A display name is a proper name, label, or title for a specific model instance. Django models already have a mechanism for providing this representation by defining the ``__str__()`` method. Why use the ``displayed`` mixin or model, then? The :py:class:`superdjango.db.displayed.mixins.DisplayNameMixin` formalizes a simple API for acquiring the proper name of a record. The ``__str__()`` method defaults to ``get_display_name()``, but may be overridden to provide something different if desired. The ``displayed`` package also defines ``get_choice_name()`` which allows the proper name to be different when the record is displayed as a choice. .. note:: Certain components of SuperDjango UI utilize a model's implementation of both ``get_choice_name()`` and ``get_display_name()``. The :py:class:`superdjango.db.displayed.mixins.DisplayNameMixin` provides the basis for this functionality. Usage ----- Simply extend :py:class:`superdjango.db.displayed.mixins.DisplayNameMixin` and implement ``get_display_name()`` or alternatively extend :py:class:`superdjango.db.displayed.models.DisplayNameModel` to also cache the the choice and display name values on ``save()``. .. _db-db-eav: EAV Models ========== |experimental| |library| **Version:** 0.6.0-x Support for the Entity Attribute Value (EAV) approach to adding custom fields. Developer Reference: :ref:`db-db-eav-developer` **Provides** - `Admin `_ : base - Constants - `Models `_ : abstract - UI : base Abstract -------- The `Entity Attribute Value model`_ (EAV) is a means of adding custom attributes to an existing model in a dynamic fashion. This can be useful for creating user-defined fields without interfering with core data models. .. _Entity Attribute Value model: https://en.wikipedia.org/wiki/Entity–attribute–value_model Usage ----- In the examples that follow, we implement a user profile model to which we wish to attach custom fields using the EAV pattern. .. code-block:: python # myapp/models.py from superdjango.db.eav.models import AttributeModel, ValueModel class Profile(models.Model): user = models.OneToOneField(AUTH_USER_MODEL, related_name="profile") # ... additional "hard coded" fields as desired ... class ExtraAttribute(AttributeModel): pass class ExtraAttributeValue(ValueModel): attribute = models.ForeignKey(ExtraAttribute, related_name="values") profile = models.ForeignKey(Profile, related_name="attributes") def get_attribute(self): return self.attribute ``ExtraAttribute`` defines the available attributes that may be populated with actual values in ``ExtraAttributeValue``. .. code-block:: python # myapp/forms.py from superdjango.forms import EAVModelForm from .models import Profile, ExtraAttribute, ExtraAttributeValue class ProfileForm(EAVModelForm): attribute_model = ExtraAttribute entity_name = "profile" value_model = ExtraAttributeValue # ... add fields and meta as usual ... Defining the attribute and value models, as well as the entity name is required. The optional ``attribute_name`` defaults to "attribute" which is what we used in ``ExtraAttributeValue`` to define the attribute model to which the value is connected. .. _db-db-expiration: Expiration Models ================= |planning| |library| **Version:** 0.7.0-p Work with records that have an expiration date and time. Developer Reference: :ref:`db-db-expiration-developer` **Provides** - `Managers `_ - `Models `_ : abstract Abstract -------- Some records represent a time-limited scope for their availability or use. The expiration library provides support for an expiration workflow. Usage ----- Suppose you have a proposal model that needs to expire after a certain date and time. .. code-block:: python # myapp/models.py from superdjango.db.expiration.managers import ExpirationManager from superdjango.db.expiration.models import ExpirationModel class Proposal(ExpirationModel): objects = ExpirationManager() # ... In the list view (for example, as displayed to clients), you may utilize the ``unexpired`` method on the manager to display only proposals that are current: .. code-block:: python from superdjango.views import ListView from .models import Proposal class ProposalList(ListView): model = Proposal def get_queryset(self): return self.model.objects.unexpired() A management command could be created to check expiration and update the expired models. .. code-block:: python # myapp/management/commands/update_expired_proposals.py from django.core.management.base import BaseCommand from myapp.models import Proposal class Command(BaseCommand): def handle(self, *args, **options): qs = Proposal.objects.filter(has_expired__is_null=True) for row in qs: if row.is_past_expiration(): row.has_expired = True row.save() .. _db-db-history: History Models ============== |planning| |library| **Version:** 0.7.0-p Abstract model for implementing audit history on models. Developer Reference: :ref:`db-db-history-developer` **Provides** - `Admin `_ : base - Constants - `Models `_ : abstract - UI : base - Utilities Abstract -------- The history package provides an abstract model for implementing a log of historical activity on other models. For a practical implementation, see ``superdjango.contrib.history``. Usage ----- Implementing Audit History .......................... You may create your own history by extending :py:class:`superdjango.db.history.models.HistoryModel`. .. code-block:: python # myapp/models.py from superdjango.db.history.models import HistoryModel class History(HistoryModel): class Meta: get_latest_by = "added_dt" ordering = ["-added_dt"] verbose_name = _("Log Entry") verbose_name_plural = _("Log Entries") See the ``admin`` and ``ui`` modules of this package for implementing Django Admin and SuperDjango UI user interfaces. Creating an Audit Trail ....................... Your view must call the ``log`` method: .. code-block:: python # myapp/views.py from .models import History class CreateTodo(CreateView): ... def form_valid(self, form): self.object = form.save() History.log(self.object, self.request.user, History.CREATE) ... Tracking Changes to Fields .......................... The :py:class:`superdjango.db.history.utils.FieldChange` may be used to assist with tracking changes to fields. The :py:func:`superdjango.db.history.utils.get_field_changes` is also provided as a shortcut for creating ``FieldChange`` instances. .. code-block:: python # myapp/models.py from superdjango.db.history.models import HistoryModel class History(HistoryModel): field_changes = models.TextField( blank=True, null=True ) class Meta: get_latest_by = "added_dt" ordering = ["-added_dt"] verbose_name = _("Log Entry") verbose_name_plural = _("Log Entries") @classmethod def log_field_changes(cls, instance, verb, fields=None): if fields is None: return a = list() for change in fields: a.append(str(change)) instance.field_changes = "\n".join(a) # myapp/views.py from superdjango.db.history.utils import get_field_changes from .models import History class UpdateTodo(UpdateView): ... def form_valid(self, form): self.object = form.save() field_changes = get_field_changes(form, self.model, record=self.object) History.log(self.object, self.request.user, History.UPDATE, fields=field_changes) ... You could also implement a separate model to record each field change and connect it to the history record. .. code-block:: python # myapp/models.py from superdjango.db.history.models import HistoryModel class History(HistoryModel): ... @classmethod def log_field_changes(cls, instance, verb, fields=None): if fields is None: return a = list() for change in fields: field_history = FieldHistory( field_label=change.field_label, field_name=change.field_name history=instance, new_value=change.new_value, old_value=change.old_value, ) field_history.save() class FieldHistory(models.Model): field_label = models.CharField( max_length=256 ) field_name = models.CharField( max_length=256 ) history = models.ForeignKey( History, on_delete=models.CASCADE, related_name="field_changes", verbose_name=_("History") ) new_value = models.TextField( blank=True, null=True ) old_value = models.TextField( blank=True, null=True ) class Meta: ordering = ["field_label"] verbose_name = _("Field History") verbose_name_plural = _("Field Histories") def __str__(self): return "%s: %s -> %s" % (self.field_label, self.old_value, self.new_value) Note that custom views or UI would be required to display the field history records. .. _db-db-locked: Locked Models ============= |planning| |library| **Version:** 0.7.1-p Work with records that have been locked from update or delete. Developer Reference: :ref:`db-db-locked-developer` **Provides** - `Admin `_ : base - `Managers `_ - `Models `_ : abstract Abstract -------- Record locking prevents delete or update actions. This library provides model-level support for locked records. Usage ----- Supporting Record Locking ......................... While the :py:class:`superdjango.db.locked.models.LockedModel` provides support for locking a record, additional work is required in the UI to prevent changes from occurring. SuperDjango UI supports locked models in the ``check_lock()`` and ``check_permission()`` methods of :py:class:`superdjango.ui.options.interfaces.BaseModelUI`. Also, the provided :py:class:`superdjango.db.locked.admin.BaseLockedModelAdmin` provides built-in support for the Django Admin. .. note:: In both of the implementations above, the super user always retains the permission to delete and update locked records. Custom views, however, will need to implement support for checking and dealing with locks. Record Lock or Unlock Permissions ................................. The provided resources assume that a super user can always lock or unlock records, and may work with records regardless of their locked status. Although it requires additional customization, you may implement custom permissions that allow authorized users to work with record locking. .. code-block:: python # myapp/models.py from superdjango.db.locked.models import LockedModel class Employee(LockedModel): # ... class Meta: permissions = [ ("can_deleted_locked_employee", "Can delete a locked employee record."), ("can_lock_employee", "Can lock an employee record."), ("can_unlock_employee", "Can unlock an employee record."), ("can_update_locked_employee", "Can update a locked employee record."), ] With these permissions in place you would need to potentially do the following depending on your needs: 1. Override the ``check_lock()`` method of :py:class:`superdjango.ui.options.interfaces.BaseModelUI` to check the custom permissions. 2. Override the ``has_delete_permission()`` and ``has_change_permission()`` methods of :py:class:`superdjango.db.locked.admin.BaseLockedModelAdmin` to check custom permissions. 3. Deal with these permissions in any custom views you have created. .. _db-db-lookups: Lookup Models ============= |development| |library| **Version:** 0.9.0-d Provides pre-defined models for managing lookup (aka validation) data. Developer Reference: :ref:`db-db-lookups-developer` **Provides** - `Admin `_ : base - `Models `_ : abstract Abstract -------- The need for lookup data (also known as validation data) is common to perhaps all Web applications. Handling such data in a consistent manager can be very beneficial to a project -- there is no need to guess as to the available fields on a lookup. .. _db-db-owned: Owned Models ============ |development| |library| **Version:** 0.12.1-d Provides a random character field. Developer Reference: :ref:`db-db-owned-developer` **Provides** - `Admin `_ : base - `Managers `_ - `Models `_ : abstract .. _db-db-parent: Parent-Tree Models ================== |experimental| |library| **Version:** 0.7.0-x Provides a simple model for implementing parent-child-sibling relationships. Developer Reference: :ref:`db-db-parent-developer` **Provides** - Compat - `Models `_ : abstract - Utilities **Dependencies** - `anytree `_ (optional) *Required to use the diagramming functionality.* This is a simplistic implementation of tree-like functionality using only a ``parent`` field that refers to ``self``. It performs well for a relatively small number of records. For thousands records, you may wish to review the following resources: - `MPTT`_ - `Treebeard`_ .. _MPTT: https://django-mptt.readthedocs.io/en/latest/index.html .. _Treebeard: http://django-treebeard.readthedocs.io/en/latest/index.html Graphing -------- Parent-tree provides a utility for creating a visual graph of a given record and all of its children. .. important:: The ``anytree`` package is required to utilize this functionality. The :py:class:`superdjango.db.parent.utils.Diagram` class may be used to create an image. Suppose you have an HR tool and you want to present the structure of an organization: .. code-block:: python from django.conf import settings import os from superdjango.db.parent.utils import Diagram from hr.organizations.models import Organization # Load the graphing utility. org = Organization.objects.get(pk=1) diagram = Diagram(org) # Output the image. graph = diagram.to_graph() path = os.path.join(settings.MEDIA_ROOT, "hr", "orgs", "%s.jpg" % org.pk) graph.to_picture(path) .. _db-db-polymorphic: Polymorphic Models ================== |experimental| |library| **Version:** 0.4.0-x Managers and mixins for polymorphic behavior. Developer Reference: :ref:`db-db-polymorphic-developer` **Provides** - `Models `_ : managers, mixins - Utilities Provides assistance with managing `Multi-table inheritance`_ in Django. .. _Multi-table inheritance: https://docs.djangoproject.com/en/stable/topics/db/models/#multi-table-inheritance .. code-block:: python from superdjango.polymophric import PolymorphicManager, PolymorphicMixin class Project(models.Model): objects = PolymorphicManager() # ... class MobileProject(PolymorphicMixin, Project): # ... class WebSiteProject(PolymorphicMixin, Project): # ... projects = Project.objects.all().select_subclasses() for project in projects: # project will be a specific instance of Project, MobileProject, or WebSiteProject. print(project) .. _db-db-primary: Primary Models ============== |experimental| |library| **Version:** 0.7.0-x Provides support for a publishing workflow. Developer Reference: :ref:`db-db-primary-developer` **Provides** - `Admin `_ : base - `Managers `_ - `Models `_ : abstract, mixins .. _db-db-published: Published Models ================ |development| |library| **Version:** 0.10.0-d Provides support for a publishing workflow. Developer Reference: :ref:`db-db-published-developer` **Provides** - `Admin `_ : base - `Models `_ : abstract .. _db-db-random: Random Models ============= |experimental| |library| **Version:** 0.6.0-x Provides a random character field. Developer Reference: :ref:`db-db-random-developer` .. _db-db-resolved: Resolved Models =============== |development| |library| **Version:** 0.3.0-d Provides support for a resolution workflow. Developer Reference: :ref:`db-db-resolved-developer` **Provides** - `Admin `_ : base - `Models `_ : abstract .. _db-db-reviewed: Reviewed Models =============== |development| |library| **Version:** 0.3.0-d Provides support for a review workflow. Developer Reference: :ref:`db-db-reviewed-developer` **Provides** - `Admin `_ : base - `Models `_ : abstract .. _db-db-revised: Revised Models ============== |experimental| |library| **Version:** 0.2.0-x A simple package that allows saving revisions of a record. Developer Reference: :ref:`db-db-revised-developer` **Provides** - `Managers `_ - `Models `_ : abstract Abstract -------- Record revision means creating a new (or latest) revision of a record whilst saving past revisions of the same record. This package supports a simple record revision system. We are fully aware of the `sundry tools for managing versioned model data`_. Many of these bring great functionality to the table, and you are encouraged to check these out as an alternative to this package. .. _sundry tools for managing versioned model data: https://djangopackages.org/grids/g/versioning/ Usage ----- After extending :py:class:`superdjango.db.revised.models.RevisedModel`, you may create a new revision of the current record using the ``save_revision()`` method. .. _db-db-sorted: Sorted Models ============= |experimental| |library| **Version:** 0.7.0-x A model and utilities for implementing record sortation. Developer Reference: :ref:`db-db-sorted-developer` **Provides** - `Models `_ : abstract - Utilities .. _db-db-slug: Slug Fields =========== |experimental| |library| **Version:** 0.4.0-x Provides support for a automatic slug field. Developer Reference: :ref:`db-db-slug-developer` **Provides** - `Models `_ : fields - Utilities Abstract -------- Support for automatic slug fields. Usage ----- The automatic slug field will by default create a slug using Django's ``slugify()`` utility. You may provide your own callback function to use for providing the slug. .. code-block:: python # myapp/models.py superdjango.db.slug.fields import AutoSlugField function underscores_and_lower_case(value): return value.replace(" ", "_").lower() class UploadFile(models.Model): file_name = AutoSlugField(from_field="title", slug_using=underscores_and_lower_case) title = models.CharField(max_length=128) # ... .. _db-db-timed: Timed Models ============ |experimental| |library| **Version:** 0.6.0-x Create records that incorporate start/stop timing functionality. Developer Reference: :ref:`db-db-timed-developer` **Provides** - `Models `_ : abstract .. _db-db-trashed: Trashed Models ============== |experimental| |library| **Version:** 0.6.1-x Provides a workflow for trashed, but not deleted, models. Developer Reference: :ref:`db-db-trashed-developer` **Provides** - `Managers `_ - `Models `_ : abstract Abstract -------- A *trashed* flag allows a single record to be marked as being removed by a user, but not yet removed from the database.