summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Holovaty <adrian@holovaty.com>2007-01-20 21:16:31 +0000
committerAdrian Holovaty <adrian@holovaty.com>2007-01-20 21:16:31 +0000
commit9c5e28e1e8c7bdd86a0fef58e8772552af6203e0 (patch)
tree27b86a65f13b329411b9bbdbaa781d215d659166
parent23b628d731b69b1cbdddc16417e109bdfe9497e1 (diff)
newforms-admin: Made the first step in converting add and change forms to use newforms. Got rid of some overengineered admin template tags along the way.
git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@4372 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--django/contrib/admin/options.py156
-rw-r--r--django/contrib/admin/templates/admin/change_form.html38
-rw-r--r--django/contrib/admin/templates/admin/field_line.html10
-rw-r--r--django/contrib/admin/templatetags/admin_modify.py43
4 files changed, 121 insertions, 126 deletions
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index 773c00fb8f..b61b0441f8 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -1,4 +1,5 @@
from django import oldforms, template
+from django import newforms as forms
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.db import models
from django.http import Http404, HttpResponse, HttpResponseRedirect
@@ -67,13 +68,63 @@ class AdminFieldLine(object):
def __len__(self):
return len(self.fields)
-# New implementation of Fieldset
+class AdminForm(object):
+ def __init__(self, form, fieldsets):
+ self.form, self.fieldsets = form, fieldsets
+
+ def __iter__(self):
+ for fieldset in self.fieldsets:
+ yield BoundFieldset(self.form, fieldset)
+
class Fieldset(object):
def __init__(self, name=None, fields=(), classes=(), description=None):
self.name, self.fields = name, fields
self.classes = ' '.join(classes)
self.description = description
+class BoundFieldset(object):
+ def __init__(self, form, fieldset):
+ self.form, self.fieldset = form, fieldset
+
+ def __iter__(self):
+ for field in self.fieldset.fields:
+ yield BoundFieldline(self.form, field)
+
+class BoundFieldline(object):
+ def __init__(self, form, field):
+ self.form = form # A django.forms.Form instance
+ if isinstance(field, basestring):
+ self.fields = [field]
+ else:
+ self.fields = field
+
+ def __iter__(self):
+ for i, field in enumerate(self.fields):
+ yield BoundField(self.form, field, is_first=(i == 0))
+
+ def errors(self):
+ return u'\n'.join([self.form[f].errors.as_ul() for f in self.fields])
+
+class BoundField(object):
+ def __init__(self, form, field, is_first):
+ self.field = form[field] # A django.forms.BoundField instance
+ self.is_first = is_first # Whether this field is first on the line
+ self.is_checkbox = isinstance(self.field.field.widget, forms.CheckboxInput)
+
+ def label_tag(self):
+ classes = []
+ if self.is_checkbox:
+ classes.append('vCheckboxLabel')
+ contents = escape(self.field.label)
+ else:
+ contents = escape(self.field.label) + ':'
+ if self.field.field.required:
+ classes.append('required')
+ if not self.is_first:
+ classes.append('inline')
+ attrs = classes and {'class': ' '.join(classes)} or {}
+ return self.field.label_tag(contents=contents, attrs=attrs)
+
class ModelAdmin(object):
"Encapsulates all admin options and functionality for a given model."
@@ -202,18 +253,16 @@ class ModelAdmin(object):
# Object list will give 'Permission Denied', so go back to admin home
post_url = '../../../'
- manipulator = model.AddManipulator()
+ ModelForm = forms.form_for_model(model)
+
if request.POST:
new_data = request.POST.copy()
-
if opts.has_field_type(models.FileField):
new_data.update(request.FILES)
+ form = ModelForm(new_data)
- errors = manipulator.get_validation_errors(new_data)
- manipulator.do_html2python(new_data)
-
- if not errors:
- new_object = manipulator.save(new_data)
+ if form.is_valid():
+ new_object = form.save(commit=True)
pk_value = new_object._get_pk_val()
LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, str(new_object), ADDITION)
msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': opts.verbose_name, 'obj': new_object}
@@ -236,25 +285,17 @@ class ModelAdmin(object):
request.user.message_set.create(message=msg)
return HttpResponseRedirect(post_url)
else:
- # Add default data.
- new_data = manipulator.flatten_data()
-
- # Override the defaults with GET params, if they exist.
- new_data.update(dict(request.GET.items()))
-
- errors = {}
-
- # Populate the FormWrapper.
- form = oldforms.FormWrapper(manipulator, new_data, errors)
+ form = ModelForm(initial=request.GET)
c = template.RequestContext(request, {
'title': _('Add %s') % opts.verbose_name,
- 'oldform': form,
+ 'adminform': AdminForm(form, self.fieldsets_add(request)),
+ 'oldform': oldforms.FormWrapper(model.AddManipulator(), {}, {}),
'is_popup': request.REQUEST.has_key('_popup'),
'show_delete': False,
})
- return render_change_form(self, model, manipulator, c, add=True)
+ return render_change_form(self, model, model.AddManipulator(), c, add=True)
def change_view(self, request, object_id):
"The 'change' admin view for this model."
@@ -272,32 +313,33 @@ class ModelAdmin(object):
return self.add_view(request, form_url='../../add/')
try:
- manipulator = model.ChangeManipulator(object_id)
+ obj = model._default_manager.get(pk=object_id)
except model.DoesNotExist:
raise Http404('%s object with primary key %r does not exist' % (model_name, escape(object_id)))
+ ModelForm = forms.form_for_instance(obj)
+
if request.POST:
new_data = request.POST.copy()
-
if opts.has_field_type(models.FileField):
new_data.update(request.FILES)
+ form = ModelForm(new_data)
- errors = manipulator.get_validation_errors(new_data)
- manipulator.do_html2python(new_data)
-
- if not errors:
- new_object = manipulator.save(new_data)
+ if form.is_valid():
+ new_object = form.save(commit=True)
pk_value = new_object._get_pk_val()
- # Construct the change message.
+ # Construct the change message. TODO: Temporarily commented-out,
+ # as manipulator object doesn't exist anymore, and we don't yet
+ # have a way to get fields_added, fields_changed, fields_deleted.
change_message = []
- if manipulator.fields_added:
- change_message.append(_('Added %s.') % get_text_list(manipulator.fields_added, _('and')))
- if manipulator.fields_changed:
- change_message.append(_('Changed %s.') % get_text_list(manipulator.fields_changed, _('and')))
- if manipulator.fields_deleted:
- change_message.append(_('Deleted %s.') % get_text_list(manipulator.fields_deleted, _('and')))
- change_message = ' '.join(change_message)
+ #if manipulator.fields_added:
+ #change_message.append(_('Added %s.') % get_text_list(manipulator.fields_added, _('and')))
+ #if manipulator.fields_changed:
+ #change_message.append(_('Changed %s.') % get_text_list(manipulator.fields_changed, _('and')))
+ #if manipulator.fields_deleted:
+ #change_message.append(_('Deleted %s.') % get_text_list(manipulator.fields_deleted, _('and')))
+ #change_message = ' '.join(change_message)
if not change_message:
change_message = _('No fields changed.')
LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, str(new_object), CHANGE, change_message)
@@ -319,41 +361,31 @@ class ModelAdmin(object):
request.user.message_set.create(message=msg)
return HttpResponseRedirect("../")
else:
- # Populate new_data with a "flattened" version of the current data.
- new_data = manipulator.flatten_data()
-
- # TODO: do this in flatten_data...
- # If the object has ordered objects on its admin page, get the existing
- # order and flatten it into a comma-separated list of IDs.
- id_order_list = []
- for rel_obj in opts.get_ordered_objects():
- id_order_list.extend(getattr(manipulator.original_object, 'get_%s_order' % rel_obj.object_name.lower())())
- if id_order_list:
- new_data['order_'] = ','.join(map(str, id_order_list))
- errors = {}
+ form = ModelForm()
- # Populate the FormWrapper.
- form = oldforms.FormWrapper(manipulator, new_data, errors)
- form.original = manipulator.original_object
- form.order_objects = []
+ ## Populate the FormWrapper.
+ #oldform = oldforms.FormWrapper(manipulator, new_data, errors)
+ #oldform.original = manipulator.original_object
+ #oldform.order_objects = []
- # TODO: Should be done in flatten_data / FormWrapper construction
- for related in opts.get_followed_related_objects():
- wrt = related.opts.order_with_respect_to
- if wrt and wrt.rel and wrt.rel.to == opts:
- func = getattr(manipulator.original_object, 'get_%s_list' %
- related.get_accessor_name())
- orig_list = func()
- form.order_objects.extend(orig_list)
+ ## TODO: Should be done in flatten_data / FormWrapper construction
+ #for related in opts.get_followed_related_objects():
+ #wrt = related.opts.order_with_respect_to
+ #if wrt and wrt.rel and wrt.rel.to == opts:
+ #func = getattr(manipulator.original_object, 'get_%s_list' %
+ #related.get_accessor_name())
+ #orig_list = func()
+ #oldform.order_objects.extend(orig_list)
c = template.RequestContext(request, {
'title': _('Change %s') % opts.verbose_name,
- 'oldform': form,
+ 'adminform': AdminForm(form, self.fieldsets_change(request, object_id)),
+ 'oldform': oldforms.FormWrapper(model.ChangeManipulator(object_id), {}, {}),
'object_id': object_id,
- 'original': manipulator.original_object,
+ 'original': obj,
'is_popup': request.REQUEST.has_key('_popup'),
})
- return render_change_form(self, model, manipulator, c, change=True)
+ return render_change_form(self, model, model.ChangeManipulator(object_id), c, change=True)
def changelist_view(self, request):
"The 'change list' admin view for this model."
diff --git a/django/contrib/admin/templates/admin/change_form.html b/django/contrib/admin/templates/admin/change_form.html
index 13d862a9f7..23c02fdb86 100644
--- a/django/contrib/admin/templates/admin/change_form.html
+++ b/django/contrib/admin/templates/admin/change_form.html
@@ -34,24 +34,34 @@
<div>
{% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}
{% if save_on_top %}{% submit_row %}{% endif %}
-{% if oldform.error_dict %}
+{% if adminform.form.errors %}
<p class="errornote">
- {% blocktrans count oldform.error_dict.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
+ {% blocktrans count adminform.form.errors.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
</p>
{% endif %}
-{% for bound_field_set in bound_field_sets %}
- <fieldset class="module aligned {{ bound_field_set.classes }}">
- {% if bound_field_set.name %}<h2>{{ bound_field_set.name }}</h2>{% endif %}
- {% if bound_field_set.description %}<div class="description">{{ bound_field_set.description }}</div>{% endif %}
- {% for bound_field_line in bound_field_set %}
- {% admin_field_line bound_field_line %}
- {% for bound_field in bound_field_line %}
- {% filter_interface_script_maybe bound_field %}
+
+{% for bfset in adminform %}
+ <fieldset class="module aligned {{ bfset.fieldset.classes }}">
+ {% if bfset.fieldset.name %}<h2>{{ bfset.fieldset.name }}</h2>{% endif %}
+ {% if bfset.fieldset.description %}<div class="description">{{ bfset.fieldset.description }}</div>{% endif %}
+ {% for line in bfset %}
+ <div class="form-row{% if line.errors %} errors{% endif %}">
+ {{ line.errors }}
+ {% for field in line %}
+ {% if field.is_checkbox %}
+ {{ field.field }}{{ field.label_tag }}
+ {% else %}
+ {{ field.label_tag }}{{ field.field }}
+ {% endif %}
+ {% if field.help_text %}<p class="help">{{ field.help_text }}</p>{% endif %}
{% endfor %}
+ </div>
{% endfor %}
- </fieldset>
+ </fieldset>
{% endfor %}
+
{% block after_field_sets %}{% endblock %}
+
{% if change %}
{% if ordered_objects %}
<fieldset class="module"><h2>{% trans "Ordering" %}</h2>
@@ -61,17 +71,23 @@
</div></fieldset>
{% endif %}
{% endif %}
+
{% for related_object in inline_related_objects %}{% edit_inline related_object %}{% endfor %}
+
{% block after_related_objects %}{% endblock %}
+
{% submit_row %}
+
{% if add %}
<script type="text/javascript">document.getElementById("{{ first_form_field_id }}").focus();</script>
{% endif %}
+
{% if auto_populated_fields %}
<script type="text/javascript">
{% auto_populated_field_script auto_populated_fields change %}
</script>
{% endif %}
+
</div>
</form></div>
{% endblock %}
diff --git a/django/contrib/admin/templates/admin/field_line.html b/django/contrib/admin/templates/admin/field_line.html
deleted file mode 100644
index 680830b506..0000000000
--- a/django/contrib/admin/templates/admin/field_line.html
+++ /dev/null
@@ -1,10 +0,0 @@
-{% load admin_modify %}
-<div class="{{ class_names }}" >
-{% for bound_field in bound_fields %}{{ bound_field.html_error_list }}{% endfor %}
-{% for bound_field in bound_fields %}
- {% if bound_field.has_label_first %}{% field_label bound_field %}{% endif %}
- {% field_widget bound_field %}
- {% if not bound_field.has_label_first %}{% field_label bound_field %}{% endif %}
- {% if bound_field.field.help_text %}<p class="help">{{ bound_field.field.help_text }}</p>{% endif %}
-{% endfor %}
-</div>
diff --git a/django/contrib/admin/templatetags/admin_modify.py b/django/contrib/admin/templatetags/admin_modify.py
index e51d458998..d36ec3389f 100644
--- a/django/contrib/admin/templatetags/admin_modify.py
+++ b/django/contrib/admin/templatetags/admin_modify.py
@@ -48,22 +48,6 @@ def submit_row(context):
}
submit_row = register.inclusion_tag('admin/submit_line.html', takes_context=True)(submit_row)
-def field_label(bound_field):
- class_names = []
- if isinstance(bound_field.field, models.BooleanField):
- class_names.append("vCheckboxLabel")
- colon = ""
- else:
- if not bound_field.field.blank:
- class_names.append('required')
- if not bound_field.first:
- class_names.append('inline')
- colon = ":"
- class_str = class_names and ' class="%s"' % ' '.join(class_names) or ''
- return '<label for="%s"%s>%s%s</label> ' % (bound_field.element_id, class_str, \
- capfirst(bound_field.field.verbose_name), colon)
-field_label = register.simple_tag(field_label)
-
class FieldWidgetNode(template.Node):
nodelists = {}
default = None
@@ -216,30 +200,3 @@ def edit_inline(parser, token):
raise template.TemplateSyntaxError, "%s takes 1 argument" % bits[0]
return EditInlineNode(bits[1])
edit_inline = register.tag(edit_inline)
-
-def admin_field_line(context, argument_val):
- if isinstance(argument_val, AdminBoundField):
- bound_fields = [argument_val]
- else:
- bound_fields = [bf for bf in argument_val]
- add = context['add']
- change = context['change']
-
- class_names = ['form-row']
- for bound_field in bound_fields:
- for f in bound_field.form_fields:
- if f.errors():
- class_names.append('errors')
- break
-
- # Assumes BooleanFields won't be stacked next to each other!
- if isinstance(bound_fields[0].field, models.BooleanField):
- class_names.append('checkbox-row')
-
- return {
- 'add': context['add'],
- 'change': context['change'],
- 'bound_fields': bound_fields,
- 'class_names': " ".join(class_names),
- }
-admin_field_line = register.inclusion_tag('admin/field_line.html', takes_context=True)(admin_field_line)