summaryrefslogtreecommitdiffstats
path: root/feincms/admin/editor.py
diff options
context:
space:
mode:
authorsubstantialnoninfringinguser <substantialnoninfringinguser@gmail.com>2009-05-21 19:47:19 +0100
committersubstantialnoninfringinguser <substantialnoninfringinguser@gmail.com>2009-05-21 19:47:19 +0100
commit54a62999c03f5293b42d56f9a99b1c5a3b02fa5f (patch)
tree8221aee4d3e16f1373c3162cd7c44eebb273345a /feincms/admin/editor.py
parent99949d466a0bf2667bad10f8c6c2c751036fd858 (diff)
downloadtroggle-54a62999c03f5293b42d56f9a99b1c5a3b02fa5f.tar.gz
troggle-54a62999c03f5293b42d56f9a99b1c5a3b02fa5f.tar.bz2
troggle-54a62999c03f5293b42d56f9a99b1c5a3b02fa5f.zip
[svn] Updates to allow subcave tree with nice admin.
Diffstat (limited to 'feincms/admin/editor.py')
-rw-r--r--feincms/admin/editor.py183
1 files changed, 183 insertions, 0 deletions
diff --git a/feincms/admin/editor.py b/feincms/admin/editor.py
new file mode 100644
index 0000000..c5c688b
--- /dev/null
+++ b/feincms/admin/editor.py
@@ -0,0 +1,183 @@
+import re
+
+from django import forms, template
+from django.conf import settings
+from django.contrib import admin
+from django.contrib.admin.options import IncorrectLookupParameters
+from django.contrib.admin.util import unquote
+from django.core import serializers
+from django.core.exceptions import ImproperlyConfigured
+from django.db import connection, transaction
+from django.forms.formsets import all_valid
+from django.forms.models import inlineformset_factory
+from django.http import HttpResponseRedirect, HttpResponse
+from django.shortcuts import render_to_response
+from django.utils import simplejson
+from django.utils.encoding import force_unicode
+from django.utils.functional import update_wrapper
+from django.utils.translation import ugettext_lazy as _
+
+
+
+FEINCMS_ADMIN_MEDIA = getattr(settings, 'FEINCMS_ADMIN_MEDIA', '/media/sys/feincms/')
+
+
+class ItemEditorMixin(object):
+ """
+ This mixin needs an attribute on the ModelAdmin class:
+
+ show_on_top::
+ A list of fields which should be displayed at the top of the form.
+ This does not need to (and should not) include ``template''
+ """
+
+ def change_view(self, request, object_id, extra_context=None):
+
+ if not hasattr(self.model, '_feincms_content_types'):
+ raise ImproperlyConfigured, 'You need to create at least one content type for the %s model.' % (self.model.__name__)
+
+ class ModelForm(forms.ModelForm):
+ class Meta:
+ model = self.model
+
+ class SettingsFieldset(forms.ModelForm):
+ # This form class is used solely for presentation, the data will be saved
+ # by the ModelForm above
+
+ class Meta:
+ model = self.model
+ exclude = self.show_on_top+('template',)
+
+ inline_formset_types = [(
+ content_type,
+ inlineformset_factory(self.model, content_type, extra=1)
+ ) for content_type in self.model._feincms_content_types]
+
+ opts = self.model._meta
+ app_label = opts.app_label
+ obj = self.model._default_manager.get(pk=unquote(object_id))
+
+ if not self.has_change_permission(request, obj):
+ raise PermissionDenied
+
+ if request.method == 'POST':
+ model_form = ModelForm(request.POST, request.FILES, instance=obj)
+
+ inline_formsets = [
+ formset_class(request.POST, request.FILES, instance=obj,
+ prefix=content_type.__name__.lower())
+ for content_type, formset_class in inline_formset_types]
+
+ if model_form.is_valid() and all_valid(inline_formsets):
+ model_form.save()
+ for formset in inline_formsets:
+ formset.save()
+ return HttpResponseRedirect(".")
+
+ settings_fieldset = SettingsFieldset(request.POST, instance=obj)
+ settings_fieldset.is_valid()
+ else:
+ model_form = ModelForm(instance=obj)
+ inline_formsets = [
+ formset_class(instance=obj, prefix=content_type.__name__.lower())
+ for content_type, formset_class in inline_formset_types]
+
+ settings_fieldset = SettingsFieldset(instance=obj)
+
+ content_types = []
+ for content_type in self.model._feincms_content_types:
+ content_name = content_type._meta.verbose_name
+ content_types.append((content_name, content_type.__name__.lower()))
+
+ context = {
+ 'title': _('Change %s') % force_unicode(opts.verbose_name),
+ 'opts': opts,
+ 'page': obj,
+ 'page_form': model_form,
+ 'inline_formsets': inline_formsets,
+ 'content_types': content_types,
+ 'settings_fieldset': settings_fieldset,
+ 'top_fieldset': [model_form[field] for field in self.show_on_top],
+ 'FEINCMS_ADMIN_MEDIA': FEINCMS_ADMIN_MEDIA,
+ }
+
+ return render_to_response([
+ 'admin/feincms/%s/%s/item_editor.html' % (app_label, opts.object_name.lower()),
+ 'admin/feincms/%s/item_editor.html' % app_label,
+ 'admin/feincms/item_editor.html',
+ ], context, context_instance=template.RequestContext(request))
+
+
+class TreeEditorMixin(object):
+ def changelist_view(self, request, extra_context=None):
+ # handle AJAX requests
+ if request.is_ajax():
+ cmd = request.POST.get('__cmd')
+ if cmd=='save_tree':
+ return self._save_tree(request)
+ elif cmd=='delete_item':
+ return self._delete_item(request)
+
+ return HttpResponse('Oops. AJAX request not understood.')
+
+ from django.contrib.admin.views.main import ChangeList, ERROR_FLAG
+ opts = self.model._meta
+ app_label = opts.app_label
+
+ if not self.has_change_permission(request, None):
+ raise PermissionDenied
+ try:
+ cl = ChangeList(request, self.model, self.list_display,
+ self.list_display_links, self.list_filter, self.date_hierarchy,
+ self.search_fields, self.list_select_related, self.list_per_page,
+ self.list_editable, self)
+ except IncorrectLookupParameters:
+ # Wacky lookup parameters were given, so redirect to the main
+ # changelist page, without parameters, and pass an 'invalid=1'
+ # parameter via the query string. If wacky parameters were given and
+ # the 'invalid=1' parameter was already in the query string, something
+ # is screwed up with the database, so display an error page.
+ if ERROR_FLAG in request.GET.keys():
+ return render_to_response('admin/invalid_setup.html', {'title': _('Database error')})
+ return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1')
+
+ context = {
+ 'FEINCMS_ADMIN_MEDIA': FEINCMS_ADMIN_MEDIA,
+ 'title': cl.title,
+ 'is_popup': cl.is_popup,
+ 'cl': cl,
+ 'has_add_permission': self.has_add_permission(request),
+ 'root_path': self.admin_site.root_path,
+ 'app_label': app_label,
+ 'object_list': self.model._tree_manager.all(),
+ }
+ context.update(extra_context or {})
+ return render_to_response([
+ 'admin/feincms/%s/%s/tree_editor.html' % (app_label, opts.object_name.lower()),
+ 'admin/feincms/%s/tree_editor.html' % app_label,
+ 'admin/feincms/tree_editor.html',
+ ], context, context_instance=template.RequestContext(request))
+
+ def _save_tree(self, request):
+ pagetree = simplejson.loads(request.POST['tree'])
+ # 0 = tree_id, 1 = parent_id, 2 = left, 3 = right, 4 = level, 5 = item_id
+ sql = "UPDATE %s SET %s=%%s, %s_id=%%s, %s=%%s, %s=%%s, %s=%%s WHERE %s=%%s" % (
+ self.model._meta.db_table,
+ self.model._meta.tree_id_attr,
+ self.model._meta.parent_attr,
+ self.model._meta.left_attr,
+ self.model._meta.right_attr,
+ self.model._meta.level_attr,
+ self.model._meta.pk.column)
+
+ connection.cursor().executemany(sql, pagetree)
+ transaction.commit_unless_managed()
+
+ return HttpResponse("OK", mimetype="text/plain")
+
+ def _delete_item(self, request):
+ page_id = request.POST['item_id']
+ obj = self.model._default_manager.get(pk=unquote(page_id))
+ obj.delete()
+ return HttpResponse("OK", mimetype="text/plain")
+