mirror of
https://github.com/evennia/evennia.git
synced 2026-03-30 12:37:16 +02:00
Fix get_tag error. Resolve #2128
This commit is contained in:
parent
2ec3bdce12
commit
e8220721ce
2 changed files with 115 additions and 44 deletions
|
|
@ -31,8 +31,14 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
|
||||
# Attribute manager methods
|
||||
def get_attribute(
|
||||
self, key=None, category=None, value=None, strvalue=None, obj=None, attrtype=None, **kwargs
|
||||
|
||||
self,
|
||||
key=None,
|
||||
category=None,
|
||||
value=None,
|
||||
strvalue=None,
|
||||
obj=None,
|
||||
attrtype=None,
|
||||
**kwargs
|
||||
):
|
||||
"""
|
||||
Return Attribute objects by key, by category, by value, by
|
||||
|
|
@ -76,9 +82,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
# no reason to make strvalue/value mutually exclusive at this level
|
||||
query.append(("attribute__db_value", value))
|
||||
return Attribute.objects.filter(
|
||||
pk__in=self.model.db_attributes.through.objects.filter(**dict(query)).values_list(
|
||||
"attribute_id", flat=True
|
||||
)
|
||||
pk__in=self.model.db_attributes.through.objects.filter(
|
||||
**dict(query)
|
||||
).values_list("attribute_id", flat=True)
|
||||
)
|
||||
|
||||
def get_nick(self, key=None, category=None, value=None, strvalue=None, obj=None):
|
||||
|
|
@ -104,8 +110,15 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
key=key, category=category, value=value, strvalue=strvalue, obj=obj
|
||||
)
|
||||
|
||||
def get_by_attribute(self, key=None, category=None, value=None,
|
||||
strvalue=None, attrtype=None, **kwargs):
|
||||
def get_by_attribute(
|
||||
self,
|
||||
key=None,
|
||||
category=None,
|
||||
value=None,
|
||||
strvalue=None,
|
||||
attrtype=None,
|
||||
**kwargs
|
||||
):
|
||||
"""
|
||||
Return objects having attributes with the given key, category,
|
||||
value, strvalue or combination of those criteria.
|
||||
|
|
@ -132,7 +145,10 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
|
||||
"""
|
||||
dbmodel = self.model.__dbclass__.__name__.lower()
|
||||
query = [("db_attributes__db_attrtype", attrtype), ("db_attributes__db_model", dbmodel)]
|
||||
query = [
|
||||
("db_attributes__db_attrtype", attrtype),
|
||||
("db_attributes__db_model", dbmodel),
|
||||
]
|
||||
if key:
|
||||
query.append(("db_attributes__db_key", key))
|
||||
if category:
|
||||
|
|
@ -158,11 +174,15 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
obj (list): Objects having the matching Nicks.
|
||||
|
||||
"""
|
||||
return self.get_by_attribute(key=key, category=category, strvalue=nick, attrtype="nick")
|
||||
return self.get_by_attribute(
|
||||
key=key, category=category, strvalue=nick, attrtype="nick"
|
||||
)
|
||||
|
||||
# Tag manager methods
|
||||
|
||||
def get_tag(self, key=None, category=None, obj=None, tagtype=None, global_search=False):
|
||||
def get_tag(
|
||||
self, key=None, category=None, obj=None, tagtype=None, global_search=False
|
||||
):
|
||||
"""
|
||||
Return Tag objects by key, by category, by object (it is
|
||||
stored on) or with a combination of those criteria.
|
||||
|
|
@ -206,9 +226,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
if category:
|
||||
query.append(("tag__db_category", category))
|
||||
return Tag.objects.filter(
|
||||
pk__in=self.model.db_tags.through.objects.filter(**dict(query)).values_list(
|
||||
"tag_id", flat=True
|
||||
)
|
||||
pk__in=self.model.db_tags.through.objects.filter(
|
||||
**dict(query)
|
||||
).values_list("tag_id", flat=True)
|
||||
)
|
||||
|
||||
def get_permission(self, key=None, category=None, obj=None):
|
||||
|
|
@ -279,7 +299,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
if not _Tag:
|
||||
from evennia.typeclasses.models import Tag as _Tag
|
||||
|
||||
match = kwargs.get("match", "all").lower().strip()
|
||||
anymatch = "any" == kwargs.get("match", "all").lower().strip()
|
||||
|
||||
keys = make_iter(key) if key else []
|
||||
categories = make_iter(category) if category else []
|
||||
|
|
@ -290,7 +310,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
|
||||
dbmodel = self.model.__dbclass__.__name__.lower()
|
||||
query = (
|
||||
self.filter(db_tags__db_tagtype__iexact=tagtype, db_tags__db_model__iexact=dbmodel)
|
||||
self.filter(
|
||||
db_tags__db_tagtype__iexact=tagtype, db_tags__db_model__iexact=dbmodel
|
||||
)
|
||||
.distinct()
|
||||
.order_by("id")
|
||||
)
|
||||
|
|
@ -309,28 +331,30 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
)
|
||||
clauses = Q()
|
||||
for ikey, key in enumerate(keys):
|
||||
# Keep each key and category together, grouped by AND
|
||||
clauses |= Q(db_key__iexact=key, db_category__iexact=categories[ikey])
|
||||
|
||||
# ANY mode; must match any one of the given tags/categories
|
||||
clauses |= Q(
|
||||
db_key__iexact=key, db_category__iexact=categories[ikey]
|
||||
)
|
||||
else:
|
||||
# only one or more categories given
|
||||
# import evennia;evennia.set_trace()
|
||||
clauses = Q()
|
||||
# ANY mode; must match any one of them
|
||||
for category in unique_categories:
|
||||
clauses |= Q(db_category__iexact=category)
|
||||
|
||||
tags = _Tag.objects.filter(clauses)
|
||||
query = query.filter(db_tags__in=tags).annotate(
|
||||
matches=Count("db_tags__pk", filter=Q(db_tags__in=tags), distinct=True)
|
||||
matches=Count("db_tags__pk", filter=Q(db_tags__in=tags),
|
||||
distinct=True)
|
||||
)
|
||||
|
||||
# Default ALL: Match all of the tags and optionally more
|
||||
if match == "all":
|
||||
n_req_tags = tags.count() if n_keys > 0 else n_unique_categories
|
||||
query = query.filter(matches__gte=n_req_tags)
|
||||
# ANY: Match any single tag, ordered by weight
|
||||
elif match == "any":
|
||||
if anymatch:
|
||||
# ANY: Match any single tag, ordered by weight
|
||||
query = query.order_by("-matches")
|
||||
else:
|
||||
# Default ALL: Match all of the tags and optionally more
|
||||
n_req_tags = n_keys if n_keys > 0 else n_unique_categories
|
||||
query = query.filter(matches__gte=n_req_tags)
|
||||
|
||||
return query
|
||||
|
||||
|
|
@ -388,7 +412,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
# try to get old tag
|
||||
|
||||
dbmodel = self.model.__dbclass__.__name__.lower()
|
||||
tag = self.get_tag(key=key, category=category, tagtype=tagtype, global_search=True)
|
||||
tag = self.get_tag(
|
||||
key=key, category=category, tagtype=tagtype, global_search=True
|
||||
)
|
||||
if tag and data is not None:
|
||||
# get tag from list returned by get_tag
|
||||
tag = tag[0]
|
||||
|
|
@ -402,7 +428,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
from evennia.typeclasses.models import Tag as _Tag
|
||||
tag = _Tag.objects.create(
|
||||
db_key=key.strip().lower() if key is not None else None,
|
||||
db_category=category.strip().lower() if category and key is not None else None,
|
||||
db_category=category.strip().lower()
|
||||
if category and key is not None
|
||||
else None,
|
||||
db_data=data,
|
||||
db_model=dbmodel,
|
||||
db_tagtype=tagtype.strip().lower() if tagtype is not None else None,
|
||||
|
|
@ -511,7 +539,8 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
typeclass=F("db_typeclass_path"),
|
||||
# Calculate this class' percentage of total composition
|
||||
percent=ExpressionWrapper(
|
||||
((F("count") / float(self.count())) * 100.0), output_field=FloatField()
|
||||
((F("count") / float(self.count())) * 100.0),
|
||||
output_field=FloatField(),
|
||||
),
|
||||
)
|
||||
.values("typeclass", "count", "percent")
|
||||
|
|
@ -531,7 +560,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
stats = self.get_typeclass_totals().order_by("typeclass")
|
||||
return {x.get("typeclass"): x.get("count") for x in stats}
|
||||
|
||||
def typeclass_search(self, typeclass, include_children=False, include_parents=False):
|
||||
def typeclass_search(
|
||||
self, typeclass, include_children=False, include_parents=False
|
||||
):
|
||||
"""
|
||||
Searches through all objects returning those which has a
|
||||
certain typeclass. If location is set, limit search to objects
|
||||
|
|
@ -806,7 +837,8 @@ class TypeclassManager(TypedObjectManager):
|
|||
|
||||
"""
|
||||
paths = [self.model.path] + [
|
||||
"%s.%s" % (cls.__module__, cls.__name__) for cls in self._get_subclasses(self.model)
|
||||
"%s.%s" % (cls.__module__, cls.__name__)
|
||||
for cls in self._get_subclasses(self.model)
|
||||
]
|
||||
kwargs.update({"db_typeclass_path__in": paths})
|
||||
return super().get(**kwargs)
|
||||
|
|
@ -828,7 +860,8 @@ class TypeclassManager(TypedObjectManager):
|
|||
"""
|
||||
# query, including all subclasses
|
||||
paths = [self.model.path] + [
|
||||
"%s.%s" % (cls.__module__, cls.__name__) for cls in self._get_subclasses(self.model)
|
||||
"%s.%s" % (cls.__module__, cls.__name__)
|
||||
for cls in self._get_subclasses(self.model)
|
||||
]
|
||||
kwargs.update({"db_typeclass_path__in": paths})
|
||||
return super().filter(*args, **kwargs)
|
||||
|
|
@ -843,6 +876,7 @@ class TypeclassManager(TypedObjectManager):
|
|||
|
||||
"""
|
||||
paths = [self.model.path] + [
|
||||
"%s.%s" % (cls.__module__, cls.__name__) for cls in self._get_subclasses(self.model)
|
||||
"%s.%s" % (cls.__module__, cls.__name__)
|
||||
for cls in self._get_subclasses(self.model)
|
||||
]
|
||||
return super().all().filter(db_typeclass_path__in=paths)
|
||||
|
|
|
|||
|
|
@ -58,12 +58,16 @@ class TestTypedObjectManager(EvenniaTest):
|
|||
self.obj2.tags.add("tag4")
|
||||
self.obj2.tags.add("tag2c")
|
||||
self.assertEqual(self._manager("get_by_tag", "tag1"), [self.obj1])
|
||||
self.assertEqual(set(self._manager("get_by_tag", "tag2")), set([self.obj1, self.obj2]))
|
||||
self.assertEqual(
|
||||
set(self._manager("get_by_tag", "tag2")), set([self.obj1, self.obj2])
|
||||
)
|
||||
self.assertEqual(self._manager("get_by_tag", "tag2a"), [self.obj2])
|
||||
self.assertEqual(self._manager("get_by_tag", "tag3 with spaces"), [self.obj2])
|
||||
self.assertEqual(self._manager("get_by_tag", ["tag2a", "tag2b"]), [self.obj2])
|
||||
self.assertEqual(self._manager("get_by_tag", ["tag2a", "tag1"]), [])
|
||||
self.assertEqual(self._manager("get_by_tag", ["tag2a", "tag4", "tag2c"]), [self.obj2])
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", ["tag2a", "tag4", "tag2c"]), [self.obj2]
|
||||
)
|
||||
|
||||
def test_get_by_tag_and_category(self):
|
||||
self.obj1.tags.add("tag5", "category1")
|
||||
|
|
@ -79,24 +83,57 @@ class TestTypedObjectManager(EvenniaTest):
|
|||
self.obj1.tags.add("tag8", "category6")
|
||||
self.obj2.tags.add("tag9", "category6")
|
||||
|
||||
self.assertEqual(self._manager("get_by_tag", "tag5", "category1"), [self.obj1, self.obj2])
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", "tag5", "category1"), [self.obj1, self.obj2]
|
||||
)
|
||||
self.assertEqual(self._manager("get_by_tag", "tag6", "category1"), [])
|
||||
self.assertEqual(self._manager("get_by_tag", "tag6", "category3"), [self.obj1, self.obj2])
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", "tag6", "category3"), [self.obj1, self.obj2]
|
||||
)
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", ["tag5", "tag6"], ["category1", "category3"]),
|
||||
[self.obj1, self.obj2],
|
||||
)
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", ["tag5", "tag7"], "category1"), [self.obj1, self.obj2]
|
||||
self._manager("get_by_tag", ["tag5", "tag7"], "category1"),
|
||||
[self.obj1, self.obj2],
|
||||
)
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", category="category1"), [self.obj1, self.obj2]
|
||||
)
|
||||
self.assertEqual(self._manager("get_by_tag", category="category1"), [self.obj1, self.obj2])
|
||||
self.assertEqual(self._manager("get_by_tag", category="category2"), [self.obj2])
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", category=["category1", "category3"]), [self.obj1, self.obj2]
|
||||
self._manager("get_by_tag", category=["category1", "category3"]),
|
||||
[self.obj1, self.obj2],
|
||||
)
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", category=["category1", "category2"]), [self.obj1, self.obj2]
|
||||
self._manager("get_by_tag", category=["category1", "category2"]),
|
||||
[self.obj1, self.obj2],
|
||||
)
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", category=["category5", "category4"]), []
|
||||
)
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", category="category1"), [self.obj1, self.obj2]
|
||||
)
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", category="category6"), [self.obj1, self.obj2]
|
||||
)
|
||||
|
||||
def test_get_tag_with_all(self):
|
||||
self.obj1.tags.add("tagA", "categoryA")
|
||||
self.assertEqual(
|
||||
self._manager(
|
||||
"get_by_tag", ["tagA", "tagB"], ["categoryA", "categoryB"], match="all"
|
||||
),
|
||||
[],
|
||||
)
|
||||
|
||||
def test_get_tag_with_any(self):
|
||||
self.obj1.tags.add("tagA", "categoryA")
|
||||
self.assertEqual(
|
||||
self._manager(
|
||||
"get_by_tag", ["tagA", "tagB"], ["categoryA", "categoryB"], match="any"
|
||||
),
|
||||
[self.obj1],
|
||||
)
|
||||
self.assertEqual(self._manager("get_by_tag", category=["category5", "category4"]), [])
|
||||
self.assertEqual(self._manager("get_by_tag", category="category1"), [self.obj1, self.obj2])
|
||||
self.assertEqual(self._manager("get_by_tag", category="category6"), [self.obj1, self.obj2])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue