Fixed an issue where saving an attribute/tag would make duplicates.

This commit is contained in:
Kelketek Rritaa 2014-06-28 18:01:00 -05:00
parent a6187ed997
commit a1b596a847
3 changed files with 41 additions and 24 deletions

View file

@ -1,14 +1,9 @@
from django.contrib import admin
from django.contrib.admin import ModelAdmin
from django.core.urlresolvers import reverse
from django.forms import Textarea
from src.typeclasses.models import Attribute, Tag
class PickledWidget(Textarea):
pass
class TagAdmin(admin.ModelAdmin):
fields = ('db_key', 'db_category', 'db_data')
@ -26,7 +21,7 @@ class AttributeInline(admin.TabularInline):
"""
# Set this to the through model of your desired M2M when subclassing.
model = None
extra = 3
extra = 1
#form = AttributeForm
fields = ('attribute', 'key', 'value', 'strvalue')
raw_id_fields = ('attribute',)

View file

@ -34,6 +34,7 @@ import weakref
from django.db import models
from django.core.exceptions import ObjectDoesNotExist
from django.conf import settings
from django.db.models import Q
from django.utils.encoding import smart_str
from django.contrib.contenttypes.models import ContentType
@ -46,7 +47,8 @@ from src.server.models import ServerConfig
from src.typeclasses import managers
from src.locks.lockhandler import LockHandler
from src.utils import logger
from src.utils.utils import make_iter, is_iter, to_str, inherits_from, LazyLoadHandler
from src.utils.utils import (
make_iter, is_iter, to_str, inherits_from, LazyLoadHandler)
from src.utils.dbserialize import to_pickle, from_pickle
from src.utils.picklefield import PickledObjectField
@ -69,7 +71,6 @@ _DA = object.__delattr__
#
#------------------------------------------------------------
#class Attribute(SharedMemoryModel):
class Attribute(SharedMemoryModel):
"""
Abstract django model.
@ -99,20 +100,33 @@ class Attribute(SharedMemoryModel):
# These database fields are all set using their corresponding properties,
# named same as the field, but withtout the db_* prefix.
db_key = models.CharField('key', max_length=255, db_index=True)
# access through the value property
db_value = PickledObjectField('value', null=True)
# string-specific storage for quick look-up
db_strvalue = models.TextField('strvalue', null=True, blank=True)
# optional categorization of attribute
db_category = models.CharField('category', max_length=128, db_index=True, blank=True, null=True)
db_value = PickledObjectField(
'value', null=True,
help_text="The data returned when the attribute is accessed. Must be "
"written as a Python literal if editing through the admin "
"interface.")
db_strvalue = models.TextField(
'strvalue', null=True, blank=True,
help_text="String-specific storage for quick look-up")
db_category = models.CharField(
'category', max_length=128, db_index=True, blank=True, null=True,
help_text="Optional categorization of attribute.")
# Lock storage
db_lock_storage = models.TextField('locks', blank=True)
# Which model of object this Attribute is attached to (A natural key like objects.dbobject)
db_model = models.CharField('model', max_length=32, db_index=True, blank=True, null=True)
db_lock_storage = models.TextField(
'locks', blank=True,
help_text="Lockstrings for this object are stored here.")
db_model = models.CharField(
'model', max_length=32, db_index=True, blank=True, null=True,
help_text="Which model of object this attribute is attached to (A "
"natural key like objects.dbobject). You should not change "
"this value unless you know what you are doing.")
# subclass of Attribute (None or nick)
db_attrtype = models.CharField('attrtype', max_length=16, db_index=True, blank=True, null=True)
db_attrtype = models.CharField(
'attrtype', max_length=16, db_index=True, blank=True, null=True,
help_text="Subclass of Attribute (None or nick)")
# time stamp
db_date_created = models.DateTimeField('date_created', editable=False, auto_now_add=True)
db_date_created = models.DateTimeField(
'date_created', editable=False, auto_now_add=True)
# Database manager
objects = managers.AttributeManager()
@ -226,10 +240,14 @@ class AttributeHandler(object):
self._cache = None
def _recache(self):
if not self._attrtype:
attrtype = Q(db_attrtype=None) | Q(db_attrtype='')
else:
attrtype = Q(db_attrtype=self._attrtype)
self._cache = dict(("%s-%s" % (to_str(attr.db_key).lower(),
attr.db_category.lower() if attr.db_category else None), attr)
for attr in getattr(self.obj, self._m2m_fieldname).filter(
db_model=self._model, db_attrtype=self._attrtype))
db_model=self._model).filter(attrtype))
#set_attr_cache(self.obj, self._cache) # currently only for testing
def has(self, key, category=None):
@ -551,12 +569,16 @@ class TagHandler(object):
self._model = "%s.%s" % ContentType.objects.get_for_model(obj).natural_key()
self._cache = None
def _recache(self):
"Update cache from database field"
if not self._tagtype:
tagtype = Q(db_tagtype='') | Q(db_tagtype__isnull=True)
else:
tagtype = Q(db_tagtype=self._tagtype)
self._cache = dict(("%s-%s" % (tag.db_key, tag.db_category), tag)
for tag in getattr(self.obj, self._m2m_fieldname).filter(
db_model=self._model, db_tagtype=self._tagtype))
for tag in getattr(
self.obj, self._m2m_fieldname).filter(
db_model=self._model).filter(tagtype))
def add(self, tag, category=None, data=None):
"Add a new tag to the handler. Tag is a string or a list of strings."

View file

@ -161,7 +161,7 @@ class PickledFormField(CharField):
value = 'None'
try:
return literal_eval(value)
except ValueError:
except (ValueError, SyntaxError):
raise ValidationError(self.error_messages['invalid'])