Author: zain
Date: 2009-07-02 02:19:44 -0500 (Thu, 02 Jul 2009)
New Revision: 11152
Modified:
django/branches/soc2009/admin-ui/django/contrib/admin/helpers.py
django/branches/soc2009/admin-ui/django/contrib/admin/media/css/base.css
django/branches/soc2009/admin-ui/django/contrib/admin/templates/admin/edit_inline/stacked.html
django/branches/soc2009/admin-ui/django/forms/formsets.py
django/branches/soc2009/admin-ui/django/forms/models.py
Log:
[soc2009/admin-ui] A far better way to implement adding inlines using
javascript. Instead of handling all the prefix incrementing in Javascript and
losing any default values, added a way to generate a template form that can be
cloned every time a new inline is added.
This is for stacked inlines. Support for tabular and selector inlines coming
next.
Modified: django/branches/soc2009/admin-ui/django/contrib/admin/helpers.py
===================================================================
--- django/branches/soc2009/admin-ui/django/contrib/admin/helpers.py
2009-07-02 04:33:21 UTC (rev 11151)
+++ django/branches/soc2009/admin-ui/django/contrib/admin/helpers.py
2009-07-02 07:19:44 UTC (rev 11152)
@@ -114,6 +114,8 @@
yield InlineAdminForm(self.formset, form, self.fieldsets,
self.opts.prepopulated_fields, original)
for form in self.formset.extra_forms:
yield InlineAdminForm(self.formset, form, self.fieldsets,
self.opts.prepopulated_fields, None)
+
+ yield InlineAdminForm(self.formset, self.formset.empty_form,
self.fieldsets, self.opts.prepopulated_fields, None)
def fields(self):
fk = getattr(self.formset, "fk", None)
Modified:
django/branches/soc2009/admin-ui/django/contrib/admin/media/css/base.css
===================================================================
--- django/branches/soc2009/admin-ui/django/contrib/admin/media/css/base.css
2009-07-02 04:33:21 UTC (rev 11151)
+++ django/branches/soc2009/admin-ui/django/contrib/admin/media/css/base.css
2009-07-02 07:19:44 UTC (rev 11152)
@@ -350,6 +350,10 @@
background-color: #F6F6F6;
}
+.empty_form {
+ display: none;
+}
+
/* FORM DEFAULTS */
input, textarea, select {
Modified:
django/branches/soc2009/admin-ui/django/contrib/admin/templates/admin/edit_inline/stacked.html
===================================================================
---
django/branches/soc2009/admin-ui/django/contrib/admin/templates/admin/edit_inline/stacked.html
2009-07-02 04:33:21 UTC (rev 11151)
+++
django/branches/soc2009/admin-ui/django/contrib/admin/templates/admin/edit_inline/stacked.html
2009-07-02 07:19:44 UTC (rev 11152)
@@ -5,7 +5,7 @@
{{ inline_admin_formset.formset.non_form_errors }}
{% for inline_admin_form in inline_admin_formset %}
-<div class="inline-related{% if forloop.last %} last-related{% endif %}"
id="{{ inline_admin_formset.opts.verbose_name}}{{ forloop.counter }}">
+<div class="inline-related{% if forloop.last %} empty_form{% endif %}" id="{{
inline_admin_formset.opts.verbose_name}}{% if not forloop.last %}{{
forloop.counter }}{% else %}-empty{% endif %}">
<h3><b>{{ inline_admin_formset.opts.verbose_name|title }}:</b> <span
class="inline_label">{% if inline_admin_form.original %}{{
inline_admin_form.original }}{% else %} #{{ forloop.counter }}{% endif %}</span>
{% if inline_admin_formset.formset.can_delete and
inline_admin_form.original %}<span class="delete">{{
inline_admin_form.deletion_field.field }} {{
inline_admin_form.deletion_field.label_tag }}</span>{% endif %}
</h3>
@@ -22,62 +22,48 @@
</div>
{% endfor %}
-<ul class="tools add_inline">
+<ul class="tools add_inline" id="{{
inline_admin_formset.opts.verbose_name}}-addinline">
<li><a id="{{ inline_admin_formset.opts.verbose_name }}-add" class="add"
href="#">Add a {{ inline_admin_formset.opts.verbose_name }}</a></li>
</ul>
</div>
<script type="text/javascript">
-function increment_fields(el) {
- el.attr('id', el.attr('id').replace(/-(\d+)-/, function (num) {
- var newnum = parseInt(num.replace(/-/g,''))+1;
- return '-' + newnum + '-';
- }));
-
- el.attr('name', el.attr('name').replace(/-(\d+)-/, function (num) {
- var newnum = parseInt(num.replace(/-/g,''))+1;
- return '-' + newnum + '-';
- }));
-}
-
$(function() {
- var id_prefix = "{{ inline_admin_formset.opts.verbose_name }}";
- var total_forms = $('#' + id_prefix + '-group input[id$="TOTAL_FORMS"]');
- var initial_forms = $('#' + id_prefix +
'-group').find('input[id$="INITIAL_FORMS"]');
+ var prefix = "{{ inline_admin_formset.opts.verbose_name }}";
+ var id_prefix = "#" + prefix;
+ var total_forms = $(id_prefix + '-group input[id$="TOTAL_FORMS"]');
+ var initial_forms = $(id_prefix +
'-group').find('input[id$="INITIAL_FORMS"]');
- // since javascript is turned on, unhide the "add new <inline>" link and
hide the extras
+ // since javascript is turned on, unhide the "add new <inline>" link
$('.add_inline').show();
- if (parseInt(initial_forms.val()) > 0) {
- $('#' + id_prefix + '-group .inline-related:gt(' +
(initial_forms.val() - 1) + ')').remove();
+ // hide the extras, but only if there were no form errors
+ if (!$('.errornote').html()) {
+ if (parseInt(initial_forms.val()) > 0) {
+ $(id_prefix + '-group .inline-related:gt(' + (initial_forms.val()
- 1) + ')')
+ .not('.empty_form').remove();
+ }
+ else {
+ $(id_prefix + '-group
.inline-related').not('.empty_form').remove();
+ }
+
+ total_forms.val(parseInt(initial_forms.val()));
}
- else {
- $('#' + id_prefix + '-group .inline-related:gt(0)').remove();
- $('#' + id_prefix + '-group .inline-related:first').hide();
- }
-
- total_forms.val(parseInt(initial_forms.val()));
- // clicking on the "add" link will add a blank form to add a new inline
object
- $('#' + id_prefix + "-add").click(function() {
- if (parseInt(total_forms.val()) == 0) {
- $('#' + id_prefix + '-group
.inline-related:first').fadeIn('normal');
- total_forms.val(parseInt(total_forms.val()) + 1);
- return false;
- }
+ $(id_prefix + "-add").click(function() {
+ var new_inline = $(id_prefix + '-empty').clone(true)
+ .insertBefore(id_prefix +
'-addinline').fadeIn('normal');
- var last_inline = $('#' + id_prefix + '-group .inline-related:last');
- var new_inline =
last_inline.clone(true).hide().insertAfter(last_inline).fadeIn('normal');
+ var inline_template = $(new_inline).html();
+ var new_inline_html = inline_template.replace(/__prefix__/g,
total_forms.val().toString());
- new_inline.find('input, select').each(function(i) {
- increment_fields($(this));
- $(this).val("");
- });
-
total_forms.val(parseInt(total_forms.val()) + 1);
- new_inline.find(".inline_label").text('#' + total_forms.val());
+ $(new_inline).html(new_inline_html);
+ $(new_inline).attr('id', prefix + total_forms.val().toString());
+ $(new_inline).find('.inline_label').html('#' +
total_forms.val().toString());
+ $(new_inline).removeClass('empty_form');
return false;
});
Modified: django/branches/soc2009/admin-ui/django/forms/formsets.py
===================================================================
--- django/branches/soc2009/admin-ui/django/forms/formsets.py 2009-07-02
04:33:21 UTC (rev 11151)
+++ django/branches/soc2009/admin-ui/django/forms/formsets.py 2009-07-02
07:19:44 UTC (rev 11152)
@@ -118,6 +118,21 @@
return self.forms[self.initial_form_count():]
extra_forms = property(_get_extra_forms)
+ def _get_empty_form(self, **kwargs):
+ defaults = {'auto_id': self.auto_id, 'prefix':
self.add_prefix("__prefix__")}
+ if self.data or self.files:
+ defaults['data'] = self.data
+ defaults['files'] = self.files
+
+ defaults['empty_permitted'] = True
+ defaults.update(kwargs)
+
+ form = self.form(**defaults)
+ self.add_fields(form, None)
+
+ return form
+ empty_form = property(_get_empty_form)
+
# Maybe this should just go away?
def _get_cleaned_data(self):
"""
@@ -133,7 +148,7 @@
Returns a list of forms that have been marked for deletion. Raises an
AttributeError if deletion is not allowed.
"""
- if not self.can_delete:
+ if not self.is_valid or not self.can_delete:
raise AttributeError("'%s' object has no attribute
'deleted_forms'" % self.__class__.__name__)
# construct _deleted_form_indexes which is just a list of form indexes
# that have had their deletion widget set to True
@@ -154,7 +169,7 @@
Returns a list of form in the order specified by the incoming data.
Raises an AttributeError if ordering is not allowed.
"""
- if not self.can_order:
+ if not self.is_valid or not self.can_order:
raise AttributeError("'%s' object has no attribute
'ordered_forms'" % self.__class__.__name__)
# Construct _ordering, which is a list of (form_index,
order_field_value)
# tuples. After constructing this list, we'll sort it by
order_field_value
@@ -267,7 +282,7 @@
"""A hook for adding extra fields on to each form instance."""
if self.can_order:
# Only pre-fill the ordering field for initial forms.
- if index < self.initial_form_count():
+ if index != None and index < self.initial_form_count():
form.fields[ORDERING_FIELD_NAME] =
IntegerField(label=_(u'Order'), initial=index+1, required=False)
else:
form.fields[ORDERING_FIELD_NAME] =
IntegerField(label=_(u'Order'), required=False)
Modified: django/branches/soc2009/admin-ui/django/forms/models.py
===================================================================
--- django/branches/soc2009/admin-ui/django/forms/models.py 2009-07-02
04:33:21 UTC (rev 11151)
+++ django/branches/soc2009/admin-ui/django/forms/models.py 2009-07-02
07:19:44 UTC (rev 11152)
@@ -664,7 +664,10 @@
or (pk.rel and pk.rel.parent_link and
pk_is_not_editable(pk.rel.to._meta.pk)))
if pk_is_not_editable(pk) or pk.name not in form.fields:
try:
- pk_value = self.get_queryset()[index].pk
+ if index:
+ pk_value = self.get_queryset()[index].pk
+ else:
+ pk_value = None
except IndexError:
pk_value = None
if isinstance(pk, OneToOneField) or isinstance(pk, ForeignKey):
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---