Custom form/formset for adding/removing tags using the handler. Each TagAdmin used by the different typeclasses are now also required to specify a related_field, which seems redundant but is very hard to get around otherwise. Still to do - make sure that all the adds are working properly, and extend this to attributes as well, and make Tag searches still sort of useful in the admin so people can at least check names and so on

This commit is contained in:
Tehom 2016-11-07 09:00:26 -05:00 committed by Griatch
parent f5c0b8eaaa
commit 6a851750f3
4 changed files with 78 additions and 2 deletions

View file

@ -26,6 +26,7 @@ class ObjectTagInline(TagInline):
"""
model = ObjectDB.db_tags.through
related_field = "objectdb"
class ObjectCreateForm(forms.ModelForm):

View file

@ -173,6 +173,7 @@ class PlayerTagInline(TagInline):
"""
model = PlayerDB.db_tags.through
related_field = "playerdb"
class PlayerAttributeInline(AttributeInline):

View file

@ -14,6 +14,7 @@ class ScriptTagInline(TagInline):
"""
model = ScriptDB.db_tags.through
related_field = "scriptdb"
class ScriptAttributeInline(AttributeInline):

View file

@ -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."