diff --git a/django/contrib/admin/media/js/prepopulate.js b/django/contrib/admin/media/js/prepopulate.js
index 24f24f9..6d8c817 100644
a
|
b
|
|
25 | 25 | values.push($(field).val()); |
26 | 26 | } |
27 | 27 | }) |
28 | | field.val(URLify(values.join(' '), maxLength)); |
| 28 | |
| 29 | var newval = values.join(' '); |
| 30 | if (field.hasClass('vSlugField')) newval = URLify(newval, maxLength) |
| 31 | field.val(newval); |
29 | 32 | }; |
30 | 33 | |
31 | 34 | $(dependencies.join(',')).keyup(populate).change(populate).focus(populate); |
diff --git a/django/contrib/admin/media/js/prepopulate.min.js b/django/contrib/admin/media/js/prepopulate.min.js
index aa94937..0c442f8 100644
a
|
b
|
|
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); |
| 1 | (function(b){b.fn.prepopulate=function(e,f){return this.each(function(){var a=b(this);a.data("_changed",!1);a.change(function(){a.data("_changed",!0)});var d=function(){if(a.data("_changed")!=!0){var d=[];b.each(e,function(a,c){b(c).val().length>0&&d.push(b(c).val())});var c=d.join(" ");a.hasClass("vSlugField")&&(c=URLify(c,f));a.val(c)}};b(e.join(",")).keyup(d).change(d).focus(d)})}})(django.jQuery); |
| 2 | No newline at end of file |
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index e9064bb..c83f56e 100644
a
|
b
|
FORMFIELD_FOR_DBFIELD_DEFAULTS = {
|
50 | 50 | models.CharField: {'widget': widgets.AdminTextInputWidget}, |
51 | 51 | models.ImageField: {'widget': widgets.AdminFileWidget}, |
52 | 52 | models.FileField: {'widget': widgets.AdminFileWidget}, |
| 53 | models.SlugField: {'widget': widgets.AdminSlugFieldWidget}, |
53 | 54 | } |
54 | 55 | |
55 | 56 | csrf_protect_m = method_decorator(csrf_protect) |
diff --git a/django/contrib/admin/templates/admin/prepopulated_fields_js.html b/django/contrib/admin/templates/admin/prepopulated_fields_js.html
index 43ef5ba..5a4ef06 100644
a
|
b
|
|
7 | 7 | id: '#{{ field.field.auto_id }}', |
8 | 8 | dependency_ids: [], |
9 | 9 | dependency_list: [], |
10 | | maxLength: {{ field.field.field.max_length|default_if_none:"50" }} |
| 10 | maxLength: {{ field.field.field.max_length|default:'null' }} |
11 | 11 | }; |
12 | 12 | |
13 | 13 | {% for dependency in field.dependencies %} |
diff --git a/django/contrib/admin/widgets.py b/django/contrib/admin/widgets.py
index 957f94f..a7f449b 100644
a
|
b
|
class AdminCommaSeparatedIntegerFieldWidget(forms.TextInput):
|
293 | 293 | if attrs is not None: |
294 | 294 | final_attrs.update(attrs) |
295 | 295 | super(AdminCommaSeparatedIntegerFieldWidget, self).__init__(attrs=final_attrs) |
| 296 | |
| 297 | class AdminSlugFieldWidget(forms.TextInput): |
| 298 | def __init__(self, attrs=None): |
| 299 | final_attrs = {'class': 'vSlugField'} |
| 300 | if attrs is not None: |
| 301 | final_attrs.update(attrs) |
| 302 | super(AdminSlugFieldWidget, self).__init__(attrs=final_attrs) |
diff --git a/tests/regressiontests/admin_widgets/models.py b/tests/regressiontests/admin_widgets/models.py
index c187584..59d8aaf 100644
a
|
b
|
class Member(models.Model):
|
15 | 15 | |
16 | 16 | class Band(models.Model): |
17 | 17 | name = models.CharField(max_length=100) |
| 18 | slug = models.SlugField(max_length=100) |
18 | 19 | members = models.ManyToManyField(Member) |
19 | 20 | |
20 | 21 | def __unicode__(self): |
diff --git a/tests/regressiontests/admin_widgets/tests.py b/tests/regressiontests/admin_widgets/tests.py
index 8f7a36c..bda4181 100644
a
|
b
|
class AdminFormfieldForDBFieldTests(TestCase):
|
119 | 119 | def testInheritance(self): |
120 | 120 | self.assertFormfield(models.Album, 'backside_art', widgets.AdminFileWidget) |
121 | 121 | |
| 122 | def testSlugField(self): |
| 123 | self.assertFormfield(models.Band, 'slug', widgets.AdminSlugFieldWidget) |
122 | 124 | |
123 | 125 | class AdminFormfieldForDBFieldWithRequestTests(DjangoTestCase): |
124 | 126 | fixtures = ["admin-widgets-users.xml"] |
… |
… |
class RelatedFieldWidgetWrapperTests(DjangoTestCase):
|
328 | 330 | # Used to fail with a name error. |
329 | 331 | w = RelatedFieldWidgetWrapper(w, rel, admin.site) |
330 | 332 | self.assertFalse(w.can_add_related) |
| 333 | |
| 334 | class AdminSlugWidgetPrepopulate(DjangoTestCase): |
| 335 | fixtures = ["admin-widgets-users.xml"] |
| 336 | admin_root = '/widget_admin' |
| 337 | |
| 338 | def setUp(self): |
| 339 | self.client.login(username="super", password="secret") |
| 340 | |
| 341 | def tearDown(self): |
| 342 | self.client.logout() |
| 343 | |
| 344 | def test_prepopulated_slug_field_existence_and_js(self): |
| 345 | response = self.client.get('%s/admin_widgets/band/add/' % self.admin_root) |
| 346 | self.assertTrue('<input id="id_slug" type="text" class="vSlugField" name="slug" maxlength="100" />' in response.content) |
| 347 | self.assertTrue("$('.empty-form .slug').addClass('prepopulated_field');" in response.content) |
diff --git a/tests/regressiontests/admin_widgets/widgetadmin.py b/tests/regressiontests/admin_widgets/widgetadmin.py
index 6f15d92..e527f43 100644
a
|
b
|
import models
|
8 | 8 | class WidgetAdmin(admin.AdminSite): |
9 | 9 | pass |
10 | 10 | |
| 11 | class BandAdmin(admin.ModelAdmin): |
| 12 | prepopulated_fields = {'slug': ['name']} |
| 13 | |
11 | 14 | class CarAdmin(admin.ModelAdmin): |
12 | 15 | list_display = ['make', 'model', 'owner'] |
13 | 16 | list_editable = ['owner'] |
… |
… |
class EventAdmin(admin.ModelAdmin):
|
25 | 28 | site = WidgetAdmin(name='widget-admin') |
26 | 29 | |
27 | 30 | site.register(models.User) |
| 31 | site.register(models.Band, BandAdmin) |
28 | 32 | site.register(models.Car, CarAdmin) |
29 | 33 | site.register(models.CarTire, CarTireAdmin) |
30 | 34 | site.register(models.Event, EventAdmin) |