Source code for evennia.web.api.filters

"""
FilterSets allow clients to specify querystrings that will determine the data
that is retrieved in GET requests. By default, Django Rest Framework uses the
'django-filter' package as its backend. Django-filter also has a section in its
documentation specifically regarding DRF integration.

https://django-filter.readthedocs.io/en/latest/guide/rest_framework.html

"""
from typing import Union

from django.db.models import Q
from django_filters.filters import EMPTY_VALUES, CharFilter
from django_filters.rest_framework.filterset import FilterSet

from evennia.accounts.models import AccountDB
from evennia.objects.models import ObjectDB
from evennia.scripts.models import ScriptDB


[docs]def get_tag_query(tag_type: Union[str, None], key: str) -> Q: """ Returns a Q object for searching by tag names for typeclasses Args: tag_type(str or None): The type of tag (None, 'alias', etc) key (str): The name of the tag Returns: A Q object that for searching by this tag type and name """ return Q(db_tags__db_tagtype=tag_type) & Q(db_tags__db_key__iexact=key)
[docs]class TagTypeFilter(CharFilter): """ This class lets you create different filters for tags of a specified db_tagtype. """ tag_type = None
[docs] def filter(self, qs, value): # if no value is specified, we don't use the filter if value in EMPTY_VALUES: return qs # if they enter a value, we filter objects by having a tag of this type with the given name return qs.filter(get_tag_query(self.tag_type, value)).distinct()
[docs]class AliasFilter(TagTypeFilter): """A filter for objects by their aliases (tags with a tagtype of 'alias'""" tag_type = "alias"
[docs]class PermissionFilter(TagTypeFilter): """A filter for objects by their permissions (tags with a tagtype of 'permission'""" tag_type = "permission"
SHARED_FIELDS = ["db_key", "db_typeclass_path", "db_tags__db_key", "db_tags__db_category"]
[docs]class BaseTypeclassFilterSet(FilterSet): """ A parent class with filters for aliases and permissions """ name = CharFilter(lookup_expr="iexact", method="filter_name", field_name="db_key") alias = AliasFilter(lookup_expr="iexact") permission = PermissionFilter(lookup_expr="iexact")
[docs] @staticmethod def filter_name(queryset, name, value): """ Filters a queryset by aliases or the key of the typeclass Args: queryset: The queryset being filtered name: The name of the field value: The value passed in from GET params Returns: The filtered queryset """ query = Q(**{f"{name}__iexact": value}) query |= get_tag_query("alias", value) return queryset.filter(query).distinct()
[docs]class ObjectDBFilterSet(BaseTypeclassFilterSet): """ This adds filters for ObjectDB instances - characters, rooms, exits, etc """
[docs] class Meta: model = ObjectDB fields = SHARED_FIELDS + [ "db_location__db_key", "db_home__db_key", "db_location__id", "db_home__id", ]
[docs]class AccountDBFilterSet(BaseTypeclassFilterSet): """This adds filters for Account objects""" name = CharFilter(lookup_expr="iexact", method="filter_name", field_name="username")
[docs] class Meta: model = AccountDB fields = [ fi for fi in (SHARED_FIELDS + ["username", "db_is_connected", "db_is_bot"]) if fi != "db_key" ]
[docs]class ScriptDBFilterSet(BaseTypeclassFilterSet): """This adds filters for Script objects"""
[docs] class Meta: model = ScriptDB fields = SHARED_FIELDS + [ "db_desc", "db_obj__db_key", "db_obj__id", "db_account__id", "db_account__username", "db_is_active", "db_persistent", "db_interval", ]
[docs]class HelpFilterSet(FilterSet): """ Filter for help entries """ name = CharFilter(lookup_expr="iexact", method="filter_name", field_name="db_key") category = CharFilter(lookup_expr="iexact", method="filter_name", field_name="db_category") alias = AliasFilter(lookup_expr="iexact")