Fix attribute serializer, add name filter

This commit is contained in:
TehomCD 2020-03-13 21:52:03 -04:00
parent 1153433a2c
commit 75812dcdd5
2 changed files with 56 additions and 4 deletions

View file

@ -6,6 +6,7 @@ documentation specifically regarding DRF integration.
https://django-filter.readthedocs.io/en/latest/guide/rest_framework.html https://django-filter.readthedocs.io/en/latest/guide/rest_framework.html
""" """
from typing import Union
from django.db.models import Q from django.db.models import Q
from django_filters.rest_framework.filterset import FilterSet from django_filters.rest_framework.filterset import FilterSet
from django_filters.filters import CharFilter, EMPTY_VALUES from django_filters.filters import CharFilter, EMPTY_VALUES
@ -15,6 +16,19 @@ from evennia.accounts.models import AccountDB
from evennia.scripts.models import ScriptDB from evennia.scripts.models import ScriptDB
def get_tag_query(tag_type: Union[str, None], key: str) -> Q:
"""
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)
class TagTypeFilter(CharFilter): class TagTypeFilter(CharFilter):
""" """
This class lets you create different filters for tags of a specified db_tagtype. This class lets you create different filters for tags of a specified db_tagtype.
@ -26,7 +40,7 @@ class TagTypeFilter(CharFilter):
if value in EMPTY_VALUES: if value in EMPTY_VALUES:
return qs return qs
# if they enter a value, we filter objects by having a tag of this type with the given name # if they enter a value, we filter objects by having a tag of this type with the given name
return qs.filter(Q(db_tags__db_tagtype=self.tag_type) & Q(db_tags__db_key=value)) return qs.filter(get_tag_query(self.tag_type, value)).distinct()
class AliasFilter(TagTypeFilter): class AliasFilter(TagTypeFilter):
@ -46,6 +60,22 @@ class BaseTypeclassFilterSet(FilterSet):
"""A parent class with filters for aliases and permissions""" """A parent class with filters for aliases and permissions"""
alias = AliasFilter(lookup_expr="iexact") alias = AliasFilter(lookup_expr="iexact")
permission = PermissionFilter(lookup_expr="iexact") permission = PermissionFilter(lookup_expr="iexact")
name = CharFilter(lookup_expr="iexact", method="filter_name", field_name="db_key")
def filter_name(self, queryset, name, value):
"""
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()
class ObjectDBFilterSet(BaseTypeclassFilterSet): class ObjectDBFilterSet(BaseTypeclassFilterSet):
@ -58,6 +88,8 @@ class ObjectDBFilterSet(BaseTypeclassFilterSet):
class AccountDBFilterSet(BaseTypeclassFilterSet): class AccountDBFilterSet(BaseTypeclassFilterSet):
"""This adds filters for Account objects""" """This adds filters for Account objects"""
name = CharFilter(lookup_expr="iexact", method="filter_name", field_name="username")
class Meta: class Meta:
model = AccountDB model = AccountDB
fields = SHARED_FIELDS + ["username", "db_is_connected", "db_is_bot"] fields = SHARED_FIELDS + ["username", "db_is_connected", "db_is_bot"]

View file

@ -19,9 +19,26 @@ from evennia.typeclasses.tags import Tag
class AttributeSerializer(serializers.ModelSerializer): class AttributeSerializer(serializers.ModelSerializer):
value_display = serializers.SerializerMethodField(source="value")
db_value = serializers.CharField(write_only=True, required=False)
class Meta: class Meta:
model = Attribute model = Attribute
fields = ["db_key", "db_value", "db_category", "db_attrtype"] fields = ["db_key", "db_category", "db_attrtype", "value_display", "db_value"]
@staticmethod
def get_value_display(obj: Attribute) -> str:
"""
Gets the string display of an Attribute's value for serialization
Args:
obj: Attribute being serialized
Returns:
The Attribute's value in string format
"""
if obj.db_strvalue:
return obj.db_strvalue
return str(obj.value)
class TagSerializer(serializers.ModelSerializer): class TagSerializer(serializers.ModelSerializer):
@ -41,9 +58,9 @@ class TypeclassSerializerMixin(object):
might note that the methods and fields are defined here, but they're included explicitly in each child might note that the methods and fields are defined here, but they're included explicitly in each child
class. What gives? It's a DRF error: serializer method fields which are inherited do not resolve correctly class. What gives? It's a DRF error: serializer method fields which are inherited do not resolve correctly
in child classes, and as of this current version (3.11) you must have them in the child classes explicitly in child classes, and as of this current version (3.11) you must have them in the child classes explicitly
to avoid field errors. to avoid field errors. Similarly, the child classes must contain the attribute serializer explicitly to
not have them render PK-related fields.
""" """
db_attributes = AttributeSerializer(many=True)
shared_fields = ["id", "db_key", "db_attributes", "db_typeclass_path", "aliases", "tags", "permissions"] shared_fields = ["id", "db_key", "db_attributes", "db_typeclass_path", "aliases", "tags", "permissions"]
@ -82,6 +99,7 @@ class TypeclassSerializerMixin(object):
class ObjectDBSerializer(TypeclassSerializerMixin, serializers.ModelSerializer): class ObjectDBSerializer(TypeclassSerializerMixin, serializers.ModelSerializer):
db_attributes = AttributeSerializer(many=True, read_only=True)
contents = serializers.SerializerMethodField() contents = serializers.SerializerMethodField()
exits = serializers.SerializerMethodField() exits = serializers.SerializerMethodField()
tags = serializers.SerializerMethodField() tags = serializers.SerializerMethodField()
@ -120,6 +138,7 @@ class ObjectDBSerializer(TypeclassSerializerMixin, serializers.ModelSerializer):
class AccountSerializer(TypeclassSerializerMixin, serializers.ModelSerializer): class AccountSerializer(TypeclassSerializerMixin, serializers.ModelSerializer):
"""This uses the DefaultAccount object to have access to the sessions property""" """This uses the DefaultAccount object to have access to the sessions property"""
db_attributes = AttributeSerializer(many=True, read_only=True)
db_key = serializers.CharField(required=False) db_key = serializers.CharField(required=False)
session_ids = serializers.SerializerMethodField() session_ids = serializers.SerializerMethodField()
tags = serializers.SerializerMethodField() tags = serializers.SerializerMethodField()
@ -144,6 +163,7 @@ class AccountSerializer(TypeclassSerializerMixin, serializers.ModelSerializer):
class ScriptDBSerializer(TypeclassSerializerMixin, serializers.ModelSerializer): class ScriptDBSerializer(TypeclassSerializerMixin, serializers.ModelSerializer):
db_attributes = AttributeSerializer(many=True, read_only=True)
tags = serializers.SerializerMethodField() tags = serializers.SerializerMethodField()
aliases = serializers.SerializerMethodField() aliases = serializers.SerializerMethodField()
permissions = serializers.SerializerMethodField() permissions = serializers.SerializerMethodField()