mirror of
https://github.com/evennia/evennia.git
synced 2026-03-28 02:36:32 +01:00
Removed LiteAttributes, made Nicks use Attributes. Added category and strvalue fields to Attribute. Made Attributes accessible through an AttributeHandler, like most other advanced properties.
This commit is contained in:
parent
befe6a6db0
commit
2f5c895f76
9 changed files with 609 additions and 420 deletions
|
|
@ -18,7 +18,7 @@ import traceback
|
|||
from django.db import models
|
||||
from django.conf import settings
|
||||
|
||||
from src.typeclasses.models import TypedObject, TagHandler, NickHandler, AliasHandler
|
||||
from src.typeclasses.models import TypedObject, TagHandler, NickHandler, AliasHandler, AttributeHandler
|
||||
from src.server.caches import get_field_cache, set_field_cache, del_field_cache
|
||||
from src.server.caches import get_prop_cache, set_prop_cache
|
||||
|
||||
|
|
@ -140,9 +140,10 @@ class ObjectDB(TypedObject):
|
|||
_SA(self, "cmdset", CmdSetHandler(self))
|
||||
_GA(self, "cmdset").update(init_mode=True)
|
||||
_SA(self, "scripts", ScriptHandler(self))
|
||||
_SA(self, "tags", TagHandler(self, category_prefix="object_"))
|
||||
_SA(self, "aliases", AliasHandler(self, category_prefix="object_"))
|
||||
_SA(self, "nicks", NickHandler(self, category_prefix="object_"))
|
||||
_SA(self, "attributes", AttributeHandler(self))
|
||||
_SA(self, "tags", TagHandler(self))
|
||||
_SA(self, "aliases", AliasHandler(self))
|
||||
_SA(self, "nicks", NickHandler(self))
|
||||
# make sure to sync the contents cache when initializing
|
||||
self.contents_update()
|
||||
|
||||
|
|
@ -646,10 +647,10 @@ class ObjectDB(TypedObject):
|
|||
raw_list = raw_string.split(None)
|
||||
raw_list = [" ".join(raw_list[:i+1]) for i in range(len(raw_list)) if raw_list[:i+1]]
|
||||
# fetch the nick data efficiently
|
||||
nicks = self.db_liteattributes.filter(db_category__in=("object_nick_inputline", "object_nick_channel")).prefetch_related("db_key","db_data")
|
||||
nicks = self.db_attributes.filter(db_category__in=("nick_inputline", "nick_channel")).prefetch_related("db_key","db_strvalue")
|
||||
if self.has_player:
|
||||
pnicks = self.player.db_liteattributes.filter(
|
||||
db_category__in=("player_nick_inputline", "player_nick_channel")).prefetch_related("db_key","db_data")
|
||||
pnicks = self.player.db_attributes.filter(
|
||||
db_category__in=("nick_inputline", "nick_channel")).prefetch_related("db_key","db_strvalue")
|
||||
nicks = list(nicks) + list(pnicks)
|
||||
for nick in nicks:
|
||||
if nick.db_key in raw_list:
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ from src.server.caches import get_field_cache, set_field_cache
|
|||
|
||||
from src.players import manager
|
||||
from src.scripts.models import ScriptDB
|
||||
from src.typeclasses.models import TypedObject, TagHandler, NickHandler, AliasHandler
|
||||
from src.typeclasses.models import TypedObject, TagHandler, NickHandler, AliasHandler, AttributeHandler
|
||||
from src.commands.cmdsethandler import CmdSetHandler
|
||||
from src.commands import cmdhandler
|
||||
from src.utils import utils
|
||||
|
|
@ -113,9 +113,10 @@ class PlayerDB(TypedObject, AbstractUser):
|
|||
# handlers
|
||||
_SA(self, "cmdset", CmdSetHandler(self))
|
||||
_GA(self, "cmdset").update(init_mode=True)
|
||||
_SA(self, "attributes", AttributeHandler(self))
|
||||
_SA(self, "tags", TagHandler(self, category_prefix="player_"))
|
||||
_SA(self, "aliases", AliasHandler(self, category_prefix="player_"))
|
||||
_SA(self, "nicks", NickHandler(self, category_prefix="player_"))
|
||||
_SA(self, "nicks", NickHandler(self))
|
||||
|
||||
# Wrapper properties to easily set database fields. These are
|
||||
# @property decorators that allows to access these fields using
|
||||
|
|
@ -483,8 +484,8 @@ class PlayerDB(TypedObject, AbstractUser):
|
|||
raw_list = raw_string.split(None)
|
||||
raw_list = [" ".join(raw_list[:i+1]) for i in range(len(raw_list)) if raw_list[:i+1]]
|
||||
# get the nick replacement data directly from the database to be able to use db_category__in
|
||||
nicks = self.db_liteattributes.filter(
|
||||
db_category__in=("object_nick_inputline", "object_nick_channel")).prefetch_related("db_key","db_data")
|
||||
nicks = self.db_attributes.filter(
|
||||
db_category__in=("nick_inputline", "nick_channel")).prefetch_related("db_key","db_strvalue")
|
||||
for nick in nicks:
|
||||
if nick.db_key in raw_list:
|
||||
raw_string = raw_string.replace(nick.db_key, nick.db_data, 1)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ from django.conf import settings
|
|||
from django.db import models
|
||||
from django.db.models.signals import post_init, pre_delete
|
||||
|
||||
from src.typeclasses.models import Attribute, TypedObject, TagHandler, AliasHandler, NickHandler
|
||||
from src.typeclasses.models import Attribute, TypedObject, TagHandler, AttributeHandler#, AliasHandler, NickHandler
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from src.scripts.manager import ScriptManager
|
||||
|
||||
|
|
@ -108,7 +108,8 @@ class ScriptDB(TypedObject):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super(ScriptDB, self).__init__(*args, **kwargs)
|
||||
_SA(self, "tags", TagHandler(self, category_prefix="script_"))
|
||||
_SA(self, "aliases", AliasHandler(self, category_prefix="script_"))
|
||||
_SA(self, "attributes", AttributeHandler(self))
|
||||
#_SA(self, "aliases", AliasHandler(self, category_prefix="script_"))
|
||||
|
||||
# Wrapper properties to easily set database fields. These are
|
||||
# @property decorators that allows to access these fields using
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwarg
|
|||
for field in update_fields:
|
||||
fieldname = field.name
|
||||
new_value = field.value_from_object(instance)
|
||||
# try to see if there is a handler on object that should be triggered when saving.
|
||||
handlername = "_%s_handler" % fieldname
|
||||
try:
|
||||
handler = _GA(instance, handlername)
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ class AttributeManager(models.Manager):
|
|||
def exists(self,*args, **kwargs):
|
||||
return super(AttributeManager, self).exists(*args, **kwargs)
|
||||
|
||||
def get_attrs_on_obj(self, searchstr, obj, exact_match=True):
|
||||
def get_attrs_on_obj(self, searchstr, obj, category=None, exact_match=True):
|
||||
"""
|
||||
Searches the object's attributes for attribute key matches.
|
||||
|
||||
|
|
@ -58,10 +58,11 @@ class AttributeManager(models.Manager):
|
|||
"""
|
||||
# Retrieve the list of attributes for this object.
|
||||
|
||||
category_cond = Q(db_category__iexact=category) if category else Q()
|
||||
if exact_match:
|
||||
return _GA("obj", "db_attributes").filter(db_key__iexact=searchstr)
|
||||
return _GA("obj", "db_attributes").filter(db_key__iexact=searchstr & category_cond)
|
||||
else:
|
||||
return _GA("obj", "db_attributes").filter(db_key__icontains=searchstr)
|
||||
return _GA("obj", "db_attributes").filter(db_key__icontains=searchstr & category_cond)
|
||||
|
||||
def attr_namesearch(self, *args, **kwargs):
|
||||
"alias wrapper for backwards compatability"
|
||||
|
|
@ -86,62 +87,6 @@ class AttributeManager(models.Manager):
|
|||
"alias wrapper for backwards compatability"
|
||||
return self.get_attr_by_value(self, *args, **kwargs)
|
||||
|
||||
#
|
||||
# LiteAttributeManager
|
||||
#
|
||||
|
||||
class LiteAttributeManager(models.Manager):
|
||||
"""
|
||||
Manager methods for LiteAttributes
|
||||
"""
|
||||
def get_lattrs_on_obj(self, obj, search_key=None, category=None):
|
||||
"""
|
||||
Get all lattrs on obj, optionally limited by key and/or category
|
||||
"""
|
||||
if search_key or category:
|
||||
key_cands = Q(db_key__iexact=search_key.lower().strip()) if search_key!=None else Q()
|
||||
cat_cands = Q(db_category__iexact=category.lower.strip()) if search_key!=None else Q()
|
||||
return _GA(obj, "db_liteattributes").filter(cat_cands & key_cands)
|
||||
else:
|
||||
return list(_GA(obj, "db_liteattributes").all())
|
||||
|
||||
def get_lattr(self, search_key=None, category=None):
|
||||
"""
|
||||
Search and return all liteattrs matching any combination of
|
||||
the search criteria.
|
||||
search_key (string) - the lattr identifier
|
||||
category (string) - the lattr category
|
||||
"""
|
||||
key_cands = Q(db_key__iexact=search_key.lower().strip()) if search_key!=None else Q()
|
||||
cat_cands = Q(db_category__iexact=category.lower.strip()) if search_key!=None else Q()
|
||||
return list(self.filter(key_cands & cat_cands))
|
||||
|
||||
def get_lattr_data(self, obj=None, search_key=None, category=None):
|
||||
"""
|
||||
Retrieve data from found lattrs in an efficient way. Returns a list of data
|
||||
matching the search criterions
|
||||
"""
|
||||
key_cands = Q(db_key__iexact=search_key.lower().strip()) if search_key!=None else Q()
|
||||
cat_cands = Q(db_category__iexact=category.lower.strip()) if search_key!=None else Q()
|
||||
if obj:
|
||||
query = _GA(obj, "db_liteattributes").filter(key_cands & cat_cands).prefetch_related("db_data")
|
||||
else:
|
||||
query = self.filter(key_cands & cat_cands).prefetch_related("db_data")
|
||||
return [q.db_data for q in query]
|
||||
|
||||
def create_lattr(self, key, category=None, data=None, obj=None):
|
||||
"""
|
||||
Create a LiteAttribute. This makes sure the create case-insensitive keys.
|
||||
"""
|
||||
|
||||
lattr = self.objects.create(db_key=key.lower().strip(),
|
||||
db_category=category.lower().strip() if category!=None else None,
|
||||
db_data=str(data) if data!=None else None)
|
||||
lattr.save()
|
||||
if obj:
|
||||
obj.db_liteattributes.add(lattr)
|
||||
return lattr
|
||||
|
||||
#
|
||||
# TagManager
|
||||
#
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding field 'Attribute.db_strvalue'
|
||||
db.add_column(u'typeclasses_attribute', 'db_strvalue',
|
||||
self.gf('django.db.models.fields.TextField')(null=True, blank=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Attribute.db_category'
|
||||
db.add_column(u'typeclasses_attribute', 'db_category',
|
||||
self.gf('django.db.models.fields.CharField')(db_index=True, max_length=128, null=True, blank=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding index on 'Tag', fields ['db_category']
|
||||
db.create_index(u'typeclasses_tag', ['db_category'])
|
||||
|
||||
# Adding index on 'Tag', fields ['db_key']
|
||||
db.create_index(u'typeclasses_tag', ['db_key'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Removing index on 'Tag', fields ['db_key']
|
||||
db.delete_index(u'typeclasses_tag', ['db_key'])
|
||||
|
||||
# Removing index on 'Tag', fields ['db_category']
|
||||
db.delete_index(u'typeclasses_tag', ['db_category'])
|
||||
|
||||
# Deleting field 'Attribute.db_strvalue'
|
||||
db.delete_column(u'typeclasses_attribute', 'db_strvalue')
|
||||
|
||||
# Deleting field 'Attribute.db_category'
|
||||
db.delete_column(u'typeclasses_attribute', 'db_category')
|
||||
|
||||
|
||||
models = {
|
||||
u'typeclasses.attribute': {
|
||||
'Meta': {'object_name': 'Attribute'},
|
||||
'db_category': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '128', 'null': 'True', 'blank': 'True'}),
|
||||
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'db_strvalue': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'typeclasses.liteattribute': {
|
||||
'Meta': {'object_name': 'LiteAttribute', 'index_together': "(('db_key', 'db_category'),)"},
|
||||
'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}),
|
||||
'db_data': ('django.db.models.fields.TextField', [], {}),
|
||||
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'typeclasses.tag': {
|
||||
'Meta': {'unique_together': "(('db_key', 'db_category'),)", 'object_name': 'Tag', 'index_together': "(('db_key', 'db_category'),)"},
|
||||
'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'db_index': 'True'}),
|
||||
'db_data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'db_index': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['typeclasses']
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Deleting model 'LiteAttribute'
|
||||
db.delete_table(u'typeclasses_liteattribute')
|
||||
|
||||
def backwards(self, orm):
|
||||
# Adding index on 'LiteAttribute', fields ['db_key', 'db_category']
|
||||
db.create_index(u'typeclasses_liteattribute', ['db_key', 'db_category'])
|
||||
|
||||
# Adding model 'LiteAttribute'
|
||||
db.create_table(u'typeclasses_liteattribute', (
|
||||
('db_category', self.gf('django.db.models.fields.CharField')(max_length=64, null=True, blank=True)),
|
||||
('db_key', self.gf('django.db.models.fields.CharField')(max_length=255)),
|
||||
('db_data', self.gf('django.db.models.fields.TextField')()),
|
||||
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
))
|
||||
db.send_create_signal(u'typeclasses', ['LiteAttribute'])
|
||||
|
||||
|
||||
models = {
|
||||
u'typeclasses.attribute': {
|
||||
'Meta': {'object_name': 'Attribute'},
|
||||
'db_category': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '128', 'null': 'True', 'blank': 'True'}),
|
||||
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'db_strvalue': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'typeclasses.tag': {
|
||||
'Meta': {'unique_together': "(('db_key', 'db_category'),)", 'object_name': 'Tag', 'index_together': "(('db_key', 'db_category'),)"},
|
||||
'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'db_index': 'True'}),
|
||||
'db_data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'db_index': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['typeclasses']
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -11,7 +11,7 @@ import os, threading
|
|||
#from twisted.internet import reactor
|
||||
#from twisted.internet.threads import blockingCallFromThread
|
||||
from twisted.internet.reactor import callFromThread
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.core.exceptions import ObjectDoesNotExist, FieldError
|
||||
from django.db.models.base import Model, ModelBase
|
||||
from django.db.models.signals import post_save, pre_delete, post_syncdb
|
||||
from src.utils.utils import dbref, get_evennia_pids
|
||||
|
|
@ -83,7 +83,7 @@ class SharedMemoryModelBase(ModelBase):
|
|||
document this auto-wrapping in the class header, this could seem very much like magic to the user otherwise.
|
||||
"""
|
||||
super(SharedMemoryModelBase, cls).__init__(*args, **kwargs)
|
||||
def create_wrapper(cls, fieldname, wrappername):
|
||||
def create_wrapper(cls, fieldname, wrappername, editable=True):
|
||||
"Helper method to create property wrappers with unique names (must be in separate call)"
|
||||
def _get(cls, fname):
|
||||
"Wrapper for getting database field"
|
||||
|
|
@ -94,6 +94,9 @@ class SharedMemoryModelBase(ModelBase):
|
|||
return _GA(value, "typeclass")
|
||||
return value
|
||||
|
||||
def _set_nonedit(cls, fname, value):
|
||||
"Wrapper for blocking editing of field"
|
||||
raise FieldError("Field %s cannot be edited." % fname)
|
||||
def _set(cls, fname, value):
|
||||
"Wrapper for setting database field"
|
||||
#print "_set:", fname
|
||||
|
|
@ -108,7 +111,7 @@ class SharedMemoryModelBase(ModelBase):
|
|||
try:
|
||||
value = cls._default_manager.get(id=dbid)
|
||||
except ObjectDoesNotExist:
|
||||
# maybe it is just a name
|
||||
# maybe it is just a name that happens to look like a dbid
|
||||
pass
|
||||
#print "_set wrapper:", fname, value, type(value), cls._get_pk_val(cls._meta)
|
||||
_SA(cls, fname, value)
|
||||
|
|
@ -117,6 +120,9 @@ class SharedMemoryModelBase(ModelBase):
|
|||
update_fields = [fname] if _GA(cls, "_get_pk_val")(_GA(cls, "_meta")) is not None else None
|
||||
_GA(cls, "save")(update_fields=update_fields)
|
||||
|
||||
def _del_nonedit(cls, fname):
|
||||
"wrapper for not allowing deletion"
|
||||
raise FieldError("Field %s cannot be edited." % fname)
|
||||
def _del(cls, fname):
|
||||
"Wrapper for clearing database field - sets it to None"
|
||||
_SA(cls, fname, None)
|
||||
|
|
@ -125,8 +131,8 @@ class SharedMemoryModelBase(ModelBase):
|
|||
|
||||
# create class wrappers
|
||||
fget = lambda cls: _get(cls, fieldname)
|
||||
fset = lambda cls, val: _set(cls, fieldname, val)
|
||||
fdel = lambda cls: _del(cls, fieldname)
|
||||
fset = lambda cls, val: _set(cls, fieldname, val) if editable else _set_nonedit(cls, fieldname, val)
|
||||
fdel = lambda cls: _del(cls, fieldname) if editable else _del_nonedit(cls,fieldname)
|
||||
doc = "Wraps setting, saving and deleting the %s field." % fieldname
|
||||
type(cls).__setattr__(cls, wrappername, property(fget, fset, fdel, doc))
|
||||
|
||||
|
|
@ -138,11 +144,11 @@ class SharedMemoryModelBase(ModelBase):
|
|||
fieldname = field.name
|
||||
if not fieldname.startswith("db_"):
|
||||
continue
|
||||
wrappername = fieldname == "id" and "dbid" or fieldname.replace("db_", "")
|
||||
wrappername = "dbid" if fieldname == "id" else fieldname.replace("db_", "")
|
||||
if not hasattr(cls, wrappername):
|
||||
# makes sure not to overload manually created wrappers on the model
|
||||
#print "wrapping %s -> %s" % (fieldname, wrappername)
|
||||
create_wrapper(cls, fieldname, wrappername)
|
||||
create_wrapper(cls, fieldname, wrappername, editable=field.editable)
|
||||
|
||||
class SharedMemoryModel(Model):
|
||||
# CL: setting abstract correctly to allow subclasses to inherit the default
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue