Source code for parasolr.django.indexing
"""
This module provides indexing support for Django models. Also see
:class:`~parasolr.indexing.Indexable`.
To use, add :class:`ModelIndexable` as a mixin to the model class
you want to be indexed. At minimum, you'll want to extend the
`index_data` method to include the data you want in the indexed::
def index_data(self):
index_data = super().index_data()
# if there are some records that should not be included
# return id only. This will blank out any previously indexed
# values, and item will not be findable by type.
# if not ...
# del index_data['item_type']
# return index_data
# add values to index data
index_data.update({
...
})
return index_data
You can optionally extend :meth:`~parasolr.indexing.Indexable.items_to_index`
and :meth:`~parasolr.indexing.Indexable.index_item_type`.
-------------------------
"""
import logging
from parasolr.django.util import requires_django
from parasolr.indexing import Indexable
try:
from django.apps import apps
from django.db.models import Manager, Model
from django.db.models.fields import related_descriptors
except ImportError:
# define placeholder model class so ModelIndexable can be defined
class Model:
pass
logger = logging.getLogger(__name__)
[docs]@requires_django
class ModelIndexable(Model, Indexable):
# Prevent ModelIndexable from itself being indexed - only subclasses
# should be included in `Indexable.all_indexables`
class Meta:
abstract = True
# these start out empty; calculated when identifying
# dependencies below
related = {}
m2m = []
separator = "__"
[docs] @classmethod
def identify_index_dependencies(cls):
"""Identify and set lists of index dependencies for the subclass
of :class:`Indexable`.
"""
# determine and document index dependencies
# for indexable models based on index_depends_on field
# if index dependencies have already been gathered, do nothing
if cls.related or cls.m2m:
return
related = []
m2m = []
for model in cls.__subclasses__():
# if no dependencies specified, skip
if not hasattr(model, "index_depends_on"):
continue
for dep, opts in model.index_depends_on.items():
# get related model
related_model = cls.get_related_model(model, dep)
related.append((related_model, opts))
# check for through model
if hasattr(model, dep):
attr = getattr(model, dep)
if isinstance(
attr, (Manager, related_descriptors.ManyToManyDescriptor)
):
# add through model to many to many list
m2m.append(attr.through)
cls.related = related
cls.m2m = m2m