Fixed #19082 -- Enabled admin field pre-population for existing objects.

Thanks to msaelices and d1ffuz0r for the initial patch and tests.
This commit is contained in:
Julien Phalip 2013-07-30 00:21:08 -07:00
parent 6ed579e7eb
commit e351dbf6ee
5 changed files with 71 additions and 22 deletions

View File

@ -3,32 +3,37 @@
/* /*
Depends on urlify.js Depends on urlify.js
Populates a selected field with the values of the dependent fields, Populates a selected field with the values of the dependent fields,
URLifies and shortens the string. URLifies and shortens the string.
dependencies - array of dependent fields id's dependencies - array of dependent fields ids
maxLength - maximum length of the URLify'd string maxLength - maximum length of the URLify'd string
*/ */
return this.each(function() { return this.each(function() {
var field = $(this); var prepopulatedField = $(this);
field.data('_changed', false);
field.change(function() {
field.data('_changed', true);
});
var populate = function () { var populate = function () {
// Bail if the fields value has changed // Bail if the field's value has been changed by the user
if (field.data('_changed') == true) return; if (prepopulatedField.data('_changed')) {
return;
}
var values = []; var values = [];
$.each(dependencies, function(i, field) { $.each(dependencies, function(i, field) {
if ($(field).val().length > 0) { field = $(field);
values.push($(field).val()); if (field.val().length > 0) {
} values.push(field.val());
}) }
field.val(URLify(values.join(' '), maxLength)); });
prepopulatedField.val(URLify(values.join(' '), maxLength));
}; };
$(dependencies.join(',')).keyup(populate).change(populate).focus(populate); prepopulatedField.data('_changed', false);
prepopulatedField.change(function() {
prepopulatedField.data('_changed', true);
});
if (!prepopulatedField.val()) {
$(dependencies.join(',')).keyup(populate).change(populate).focus(populate);
}
}); });
}; };
})(django.jQuery); })(django.jQuery);

View File

@ -1 +1 @@
(function(a){a.fn.prepopulate=function(d,g){return this.each(function(){var b=a(this);b.data("_changed",false);b.change(function(){b.data("_changed",true)});var c=function(){if(b.data("_changed")!=true){var e=[];a.each(d,function(h,f){a(f).val().length>0&&e.push(a(f).val())});b.val(URLify(e.join(" "),g))}};a(d.join(",")).keyup(c).change(c).focus(c)})}})(django.jQuery); (function(b){b.fn.prepopulate=function(e,g){return this.each(function(){var a=b(this),d=function(){if(!a.data("_changed")){var f=[];b.each(e,function(h,c){c=b(c);c.val().length>0&&f.push(c.val())});a.val(URLify(f.join(" "),g))}};a.data("_changed",false);a.change(function(){a.data("_changed",true)});a.val()||b(e.join(",")).keyup(d).change(d).focus(d)})}})(django.jQuery);

View File

@ -9,7 +9,7 @@ def prepopulated_fields_js(context):
the prepopulated fields for both the admin form and inlines. the prepopulated fields for both the admin form and inlines.
""" """
prepopulated_fields = [] prepopulated_fields = []
if context['add'] and 'adminform' in context: if 'adminform' in context:
prepopulated_fields.extend(context['adminform'].prepopulated_fields) prepopulated_fields.extend(context['adminform'].prepopulated_fields)
if 'inline_admin_formsets' in context: if 'inline_admin_formsets' in context:
for inline_admin_formset in context['inline_admin_formsets']: for inline_admin_formset in context['inline_admin_formsets']:

View File

@ -644,8 +644,8 @@ class MainPrepopulated(models.Model):
max_length=20, max_length=20,
choices=(('option one', 'Option One'), choices=(('option one', 'Option One'),
('option two', 'Option Two'))) ('option two', 'Option Two')))
slug1 = models.SlugField() slug1 = models.SlugField(blank=True)
slug2 = models.SlugField() slug2 = models.SlugField(blank=True)
class RelatedPrepopulated(models.Model): class RelatedPrepopulated(models.Model):
parent = models.ForeignKey(MainPrepopulated) parent = models.ForeignKey(MainPrepopulated)

View File

@ -3438,6 +3438,50 @@ class SeleniumAdminViewsFirefoxTests(AdminSeleniumWebDriverTestCase):
slug2='option-one-tabular-inline-ignored-characters', slug2='option-one-tabular-inline-ignored-characters',
) )
def test_populate_existing_object(self):
"""
Ensure that the prepopulation works for existing objects too, as long
as the original field is empty.
Refs #19082.
"""
# Slugs are empty to start with.
item = MainPrepopulated.objects.create(
name=' this is the mAin nÀMë',
pubdate='2012-02-18',
status='option two',
slug1='',
slug2='',
)
self.admin_login(username='super',
password='secret',
login_url='/test_admin/admin/')
object_url = '%s%s' % (
self.live_server_url,
'/test_admin/admin/admin_views/mainprepopulated/{}/'.format(item.id))
self.selenium.get(object_url)
self.selenium.find_element_by_css_selector('#id_name').send_keys(' the best')
# The slugs got prepopulated since they were originally empty
slug1 = self.selenium.find_element_by_css_selector('#id_slug1').get_attribute('value')
slug2 = self.selenium.find_element_by_css_selector('#id_slug2').get_attribute('value')
self.assertEqual(slug1, 'main-name-best-2012-02-18')
self.assertEqual(slug2, 'option-two-main-name-best')
# Save the object
self.selenium.find_element_by_xpath('//input[@value="Save"]').click()
self.wait_page_loaded()
self.selenium.get(object_url)
self.selenium.find_element_by_css_selector('#id_name').send_keys(' hello')
# The slugs got prepopulated didn't change since they were originally not empty
slug1 = self.selenium.find_element_by_css_selector('#id_slug1').get_attribute('value')
slug2 = self.selenium.find_element_by_css_selector('#id_slug2').get_attribute('value')
self.assertEqual(slug1, 'main-name-best-2012-02-18')
self.assertEqual(slug2, 'option-two-main-name-best')
def test_collapsible_fieldset(self): def test_collapsible_fieldset(self):
""" """
Test that the 'collapse' class in fieldsets definition allows to Test that the 'collapse' class in fieldsets definition allows to