diff --git a/evennia/objects/admin.py b/evennia/objects/admin.py index 821804bf2e..7ad78a2f2a 100644 --- a/evennia/objects/admin.py +++ b/evennia/objects/admin.py @@ -26,6 +26,7 @@ class ObjectTagInline(TagInline): """ model = ObjectDB.db_tags.through + related_field = "objectdb" class ObjectCreateForm(forms.ModelForm): diff --git a/evennia/players/admin.py b/evennia/players/admin.py index ce214fa928..94ccabd547 100644 --- a/evennia/players/admin.py +++ b/evennia/players/admin.py @@ -173,6 +173,7 @@ class PlayerTagInline(TagInline): """ model = PlayerDB.db_tags.through + related_field = "playerdb" class PlayerAttributeInline(AttributeInline): diff --git a/evennia/scripts/admin.py b/evennia/scripts/admin.py index a0bafe6455..b3084da58e 100644 --- a/evennia/scripts/admin.py +++ b/evennia/scripts/admin.py @@ -14,6 +14,7 @@ class ScriptTagInline(TagInline): """ model = ScriptDB.db_tags.through + related_field = "scriptdb" class ScriptAttributeInline(AttributeInline): diff --git a/evennia/typeclasses/admin.py b/evennia/typeclasses/admin.py index 2f326a9b74..74c84bf80e 100644 --- a/evennia/typeclasses/admin.py +++ b/evennia/typeclasses/admin.py @@ -2,6 +2,7 @@ from django.contrib import admin from django.contrib.admin import ModelAdmin from django.core.urlresolvers import reverse from evennia.typeclasses.models import Attribute, Tag +from django import forms class TagAdmin(admin.ModelAdmin): @@ -15,6 +16,60 @@ class TagAdmin(admin.ModelAdmin): list_filter = ('db_tagtype',) +class TagForm(forms.ModelForm): + tag_key = forms.CharField(label='Tag Name') + tag_category = forms.CharField(label="Category", required=False) + tag_type = forms.CharField(label="Type", required=False) + tag_data = forms.CharField(label="Data", required=False) + + def __init__(self, *args, **kwargs): + super(TagForm, self).__init__(*args, **kwargs) + if hasattr(self.instance, 'tag'): + self.fields['tag_key'].initial = self.instance.tag.db_key + self.fields['tag_category'].initial = self.instance.tag.db_category + self.fields['tag_type'].initial = self.instance.tag.db_tagtype + self.fields['tag_data'].initial = self.instance.tag.db_data + + def save(self, commit=True): + # we are spoofing a tag for the Handler that will be called + #instance = super(TagForm, self).save(commit=False) + instance = self.instance + instance.tag_key = self.cleaned_data['tag_key'] + instance.tag_category = self.cleaned_data['tag_category'] or None + instance.tag_type = self.cleaned_data['tag_type'] or None + instance.tag_data = self.cleaned_data['tag_data'] or None + return instance + + +class TagFormSet(forms.BaseInlineFormSet): + def save(self, commit=True): + print "inside TagFormSet" + def get_handler(finished_object): + related = getattr(finished_object, self.related_field) + try: + tagtype = finished_object.tag_type + except AttributeError: + tagtype = finished_object.tag.db_tagtype + if tagtype == "alias": + handler_name = "aliases" + elif tagtype == "permission": + handler_name = "permissions" + else: + handler_name = "tags" + return getattr(related, handler_name) + instances = super(TagFormSet, self).save(commit=False) + for obj in self.deleted_objects: + handler = get_handler(obj) + try: + tagkey = obj.tag_key + except AttributeError: + tagkey = obj.tag.db_key + handler.remove(tagkey) + for instance in instances: + handler = get_handler(instance) + handler.add(instance.tag_key) + + class TagInline(admin.TabularInline): """ A handler for inline Tags. @@ -22,10 +77,28 @@ class TagInline(admin.TabularInline): """ # Set this to the through model of your desired M2M when subclassing. model = None - fields = ('tag', 'key', 'category', 'data', 'tagtype') + form = TagForm + formset = TagFormSet + related_field = None + #fields = ('tag', 'key', 'category', 'data', 'tagtype') raw_id_fields = ('tag',) - readonly_fields = ('key', 'category', 'data', 'tagtype') + readonly_fields = ('tag',) + #readonly_fields = ('key', 'category', 'data', 'tagtype') extra = 0 + + def get_formset(self, request, obj=None, **kwargs): + """ + get_formset has to return a class, but we need to make the class that we return + know about the related_field that we'll use. Returning the class itself rather than + a proxy isn't threadsafe, since it'd be the base class and would change if multiple + people used the admin at the same time + """ + formset = super(TagInline, self).get_formset(request, obj, **kwargs) + class ProxyFormset(formset): + pass + ProxyFormset.related_field = self.related_field + return ProxyFormset + def key(self, instance): if not instance.id: return "Not yet set or saved."