mirror of
https://github.com/django/django.git
synced 2025-07-05 18:29:11 +00:00
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
This commit is contained in:
parent
23b628d731
commit
9c5e28e1e8
@ -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()
|
||||
form = ModelForm()
|
||||
|
||||
# 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 = {}
|
||||
## Populate the FormWrapper.
|
||||
#oldform = oldforms.FormWrapper(manipulator, new_data, errors)
|
||||
#oldform.original = manipulator.original_object
|
||||
#oldform.order_objects = []
|
||||
|
||||
# Populate the FormWrapper.
|
||||
form = oldforms.FormWrapper(manipulator, new_data, errors)
|
||||
form.original = manipulator.original_object
|
||||
form.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."
|
||||
|
@ -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 %}
|
||||
|
@ -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>
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user