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
"""
from typing import Union
from django.db.models import Q
from django_filters.rest_framework.filterset import FilterSet
from django_filters.filters import CharFilter, EMPTY_VALUES
@ -15,6 +16,19 @@ from evennia.accounts.models import AccountDB
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):
"""
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:
return qs
# 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):
@ -46,6 +60,22 @@ class BaseTypeclassFilterSet(FilterSet):
"""A parent class with filters for aliases and permissions"""
alias = AliasFilter(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):
@ -58,6 +88,8 @@ class ObjectDBFilterSet(BaseTypeclassFilterSet):
class AccountDBFilterSet(BaseTypeclassFilterSet):
"""This adds filters for Account objects"""
name = CharFilter(lookup_expr="iexact", method="filter_name", field_name="username")
class Meta:
model = AccountDB
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):
value_display = serializers.SerializerMethodField(source="value")
db_value = serializers.CharField(write_only=True, required=False)
class Meta:
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):
@ -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
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
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"]
@ -82,6 +99,7 @@ class TypeclassSerializerMixin(object):
class ObjectDBSerializer(TypeclassSerializerMixin, serializers.ModelSerializer):
db_attributes = AttributeSerializer(many=True, read_only=True)
contents = serializers.SerializerMethodField()
exits = serializers.SerializerMethodField()
tags = serializers.SerializerMethodField()
@ -120,6 +138,7 @@ class ObjectDBSerializer(TypeclassSerializerMixin, serializers.ModelSerializer):
class AccountSerializer(TypeclassSerializerMixin, serializers.ModelSerializer):
"""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)
session_ids = serializers.SerializerMethodField()
tags = serializers.SerializerMethodField()
@ -144,6 +163,7 @@ class AccountSerializer(TypeclassSerializerMixin, serializers.ModelSerializer):
class ScriptDBSerializer(TypeclassSerializerMixin, serializers.ModelSerializer):
db_attributes = AttributeSerializer(many=True, read_only=True)
tags = serializers.SerializerMethodField()
aliases = serializers.SerializerMethodField()
permissions = serializers.SerializerMethodField()