Author: julien
Date: 2012-02-19 08:42:12 -0800 (Sun, 19 Feb 2012)
New Revision: 17562

Modified:
   django/trunk/django/contrib/admin/templates/admin/edit_inline/stacked.html
   django/trunk/django/contrib/admin/templates/admin/edit_inline/tabular.html
   django/trunk/django/contrib/admin/templates/admin/includes/fieldset.html
   django/trunk/django/contrib/admin/templates/admin/prepopulated_fields_js.html
   django/trunk/django/contrib/admin/tests.py
   django/trunk/tests/regressiontests/admin_views/admin.py
   django/trunk/tests/regressiontests/admin_views/models.py
   django/trunk/tests/regressiontests/admin_views/tests.py
Log:
Fixed #13068 (again) -- Corrected the admin stacked inline template to allow 
prepopulated fields to work (Thanks Stanislas Guerra for the report). Also 
fixed a regression introduced in [16953] where prepopulated fields wouldn't be 
recognized any more due to the additional "field-" CSS class name prefix.

Modified: 
django/trunk/django/contrib/admin/templates/admin/edit_inline/stacked.html
===================================================================
--- django/trunk/django/contrib/admin/templates/admin/edit_inline/stacked.html  
2012-02-19 09:22:18 UTC (rev 17561)
+++ django/trunk/django/contrib/admin/templates/admin/edit_inline/stacked.html  
2012-02-19 16:42:12 UTC (rev 17562)
@@ -27,14 +27,14 @@
                 var count = i + 1;
                 $(this).html($(this).html().replace(/(#\d+)/g, "#" + count));
             });
-        }
+        };
         var reinitDateTimeShortCuts = function() {
             // Reinitialize the calendar and clock widgets by force, yuck.
             if (typeof DateTimeShortcuts != "undefined") {
                 $(".datetimeshortcuts").remove();
                 DateTimeShortcuts.init();
             }
-        }
+        };
         var updateSelectFilter = function() {
             // If any SelectFilter widgets were added, instantiate a new 
instance.
             if (typeof SelectFilter != "undefined"){
@@ -47,7 +47,7 @@
                   SelectFilter.init(value.id, namearr[namearr.length-1], true, 
"{% static "admin/" %}");
                 });
             }
-        }
+        };
         var initPrepopulatedFields = function(row) {
             row.find('.prepopulated_field').each(function() {
                 var field = $(this);
@@ -55,13 +55,13 @@
                 var dependency_list = input.data('dependency_list') || [];
                 var dependencies = [];
                 $.each(dependency_list, function(i, field_name) {
-                  dependencies.push('#' + row.find(field_name).find('input, 
select, textarea').attr('id'));
+                  dependencies.push('#' + row.find('.form-row .field-' + 
field_name).find('input, select, textarea').attr('id'));
                 });
                 if (dependencies.length) {
                     input.prepopulate(dependencies, input.attr('maxlength'));
                 }
             });
-        }
+        };
         $(rows).formset({
             prefix: "{{ inline_admin_formset.formset.prefix }}",
             addText: "{% blocktrans with 
verbose_name=inline_admin_formset.opts.verbose_name|title %}Add another {{ 
verbose_name }}{% endblocktrans %}",

Modified: 
django/trunk/django/contrib/admin/templates/admin/edit_inline/tabular.html
===================================================================
--- django/trunk/django/contrib/admin/templates/admin/edit_inline/tabular.html  
2012-02-19 09:22:18 UTC (rev 17561)
+++ django/trunk/django/contrib/admin/templates/admin/edit_inline/tabular.html  
2012-02-19 16:42:12 UTC (rev 17562)
@@ -22,7 +22,7 @@
         {% if inline_admin_form.form.non_field_errors %}
         <tr><td colspan="{{ inline_admin_form|cell_count }}">{{ 
inline_admin_form.form.non_field_errors }}</td></tr>
         {% endif %}
-        <tr class="{% cycle "row1" "row2" %} {% if inline_admin_form.original 
or inline_admin_form.show_url %}has_original{% endif %}{% if forloop.last %} 
empty-form{% endif %}"
+        <tr class="form-row {% cycle "row1" "row2" %} {% if 
inline_admin_form.original or inline_admin_form.show_url %}has_original{% endif 
%}{% if forloop.last %} empty-form{% endif %}"
              id="{{ inline_admin_formset.formset.prefix }}-{% if not 
forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}">
         <td class="original">
           {% if inline_admin_form.original or inline_admin_form.show_url %}<p>
@@ -103,7 +103,7 @@
                 var dependency_list = input.data('dependency_list') || [];
                 var dependencies = [];
                 $.each(dependency_list, function(i, field_name) {
-                  dependencies.push('#' + row.find(field_name).find('input, 
select, textarea').attr('id'));
+                  dependencies.push('#' + row.find('.field-' + 
field_name).find('input, select, textarea').attr('id'));
                 });
                 if (dependencies.length) {
                     input.prepopulate(dependencies, input.attr('maxlength'));

Modified: 
django/trunk/django/contrib/admin/templates/admin/includes/fieldset.html
===================================================================
--- django/trunk/django/contrib/admin/templates/admin/includes/fieldset.html    
2012-02-19 09:22:18 UTC (rev 17561)
+++ django/trunk/django/contrib/admin/templates/admin/includes/fieldset.html    
2012-02-19 16:42:12 UTC (rev 17562)
@@ -7,7 +7,7 @@
         <div class="form-row{% if line.fields|length_is:'1' and line.errors %} 
errors{% endif %}{% for field in line %}{% if field.field.name %} field-{{ 
field.field.name }}{% endif %}{% endfor %}">
             {% if line.fields|length_is:'1' %}{{ line.errors }}{% endif %}
             {% for field in line %}
-                <div{% if not line.fields|length_is:'1' %} class="field-box{% 
if not field.is_readonly and field.errors %} errors{% endif %}"{% endif %}>
+                <div{% if not line.fields|length_is:'1' %} class="field-box{% 
if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not 
field.is_readonly and field.errors %} errors{% endif %}"{% endif %}>
                     {% if not line.fields|length_is:'1' and not 
field.is_readonly %}{{ field.errors }}{% endif %}
                     {% if field.is_checkbox %}
                         {{ field.field }}{{ field.label_tag }}

Modified: 
django/trunk/django/contrib/admin/templates/admin/prepopulated_fields_js.html
===================================================================
--- 
django/trunk/django/contrib/admin/templates/admin/prepopulated_fields_js.html   
    2012-02-19 09:22:18 UTC (rev 17561)
+++ 
django/trunk/django/contrib/admin/templates/admin/prepopulated_fields_js.html   
    2012-02-19 16:42:12 UTC (rev 17562)
@@ -1,7 +1,7 @@
 {% load l10n %}
 <script type="text/javascript">
 (function($) {
-    var field = null;
+    var field;
 
 {% for field in prepopulated_fields %}
     field = {
@@ -13,10 +13,13 @@
 
     {% for dependency in field.dependencies %}
     field['dependency_ids'].push('#{{ dependency.auto_id }}');
-    field['dependency_list'].push('.{{ dependency.name }}');
+    field['dependency_list'].push('{{ dependency.name }}');
     {% endfor %}
 
-    $('.empty-form .{{ field.field.name }}').addClass('prepopulated_field');
+    {% comment %}
+    Mark prepopulated fields in the main form and stacked inlines (.empty-form 
.form-row) and in tabular inlines (.empty-form.form-row)
+    {% endcomment %}
+    $('.empty-form .form-row .field-{{ field.field.name }}, 
.empty-form.form-row .field-{{ field.field.name 
}}').addClass('prepopulated_field');
     $(field.id).data('dependency_list', field['dependency_list'])
                .prepopulate(field['dependency_ids'], field.maxLength);
 {% endfor %}

Modified: django/trunk/django/contrib/admin/tests.py
===================================================================
--- django/trunk/django/contrib/admin/tests.py  2012-02-19 09:22:18 UTC (rev 
17561)
+++ django/trunk/django/contrib/admin/tests.py  2012-02-19 16:42:12 UTC (rev 
17562)
@@ -1,4 +1,5 @@
 import sys
+from selenium.common.exceptions import NoSuchElementException
 
 from django.test import LiveServerTestCase
 from django.utils.importlib import import_module
@@ -71,4 +72,16 @@
         with Django.
         """
         return self.selenium.execute_script(
-            'return django.jQuery("%s").css("%s")' % (selector, attribute))
\ No newline at end of file
+            'return django.jQuery("%s").css("%s")' % (selector, attribute))
+
+    def select_option(self, selector, value):
+        """
+        Helper function to select the <OPTION> that has the value `value` and
+        that is in the <SELECT> widget identified by the CSS selector 
`selector`.
+        """
+        options = self.selenium.find_elements_by_css_selector('%s option' % 
selector)
+        for option in options:
+            if option.get_attribute('value') == value:
+                option.click()
+                return
+        raise NoSuchElementException('Option "%s" not found in "%s"' % (value, 
selector))
\ No newline at end of file

Modified: django/trunk/tests/regressiontests/admin_views/admin.py
===================================================================
--- django/trunk/tests/regressiontests/admin_views/admin.py     2012-02-19 
09:22:18 UTC (rev 17561)
+++ django/trunk/tests/regressiontests/admin_views/admin.py     2012-02-19 
16:42:12 UTC (rev 17562)
@@ -26,7 +26,7 @@
     CoverLetter, Story, OtherStory, Book, Promo, ChapterXtra1, Pizza, Topping,
     Album, Question, Answer, ComplexSortedPerson, PrePopulatedPostLargeSlug,
     AdminOrderedField, AdminOrderedModelMethod, AdminOrderedAdminMethod,
-    AdminOrderedCallable, Report, Color2)
+    AdminOrderedCallable, Report, Color2, MainPrepopulated, 
RelatedPrepopulated)
 
 
 def callable_year(dt_value):
@@ -532,6 +532,38 @@
 class CustomTemplateFilterColorAdmin(admin.ModelAdmin):
     list_filter = (('warm', CustomTemplateBooleanFieldListFilter),)
 
+
+# For Selenium Prepopulated tests -------------------------------------
+class RelatedPrepopulatedInline1(admin.StackedInline):
+    fieldsets = (
+        (None, {
+            'fields': (('pubdate', 'status'), ('name', 'slug1', 'slug2',),)
+        }),
+    )
+    model = RelatedPrepopulated
+    extra = 1
+    prepopulated_fields = {'slug1': ['name', 'pubdate'],
+                           'slug2': ['status', 'name']}
+
+class RelatedPrepopulatedInline2(admin.TabularInline):
+    model = RelatedPrepopulated
+    extra = 1
+    prepopulated_fields = {'slug1': ['name', 'pubdate'],
+                           'slug2': ['status', 'name']}
+
+class MainPrepopulatedAdmin(admin.ModelAdmin):
+    inlines = [RelatedPrepopulatedInline1, RelatedPrepopulatedInline2]
+    fieldsets = (
+        (None, {
+            'fields': (('pubdate', 'status'), ('name', 'slug1', 'slug2',),)
+        }),
+    )
+    prepopulated_fields = {'slug1': ['name', 'pubdate'],
+                           'slug2': ['status', 'name']}
+
+
+
+
 site = admin.AdminSite(name="admin")
 site.register(Article, ArticleAdmin)
 site.register(CustomArticle, CustomArticleAdmin)
@@ -576,6 +608,7 @@
 site.register(Story, StoryAdmin)
 site.register(OtherStory, OtherStoryAdmin)
 site.register(Report, ReportAdmin)
+site.register(MainPrepopulated, MainPrepopulatedAdmin)
 
 # We intentionally register Promo and ChapterXtra1 but not Chapter nor 
ChapterXtra2.
 # That way we cover all four cases:

Modified: django/trunk/tests/regressiontests/admin_views/models.py
===================================================================
--- django/trunk/tests/regressiontests/admin_views/models.py    2012-02-19 
09:22:18 UTC (rev 17561)
+++ django/trunk/tests/regressiontests/admin_views/models.py    2012-02-19 
16:42:12 UTC (rev 17562)
@@ -575,3 +575,25 @@
 
     def __unicode__(self):
         return self.title
+
+
+class MainPrepopulated(models.Model):
+    name = models.CharField(max_length=100)
+    pubdate = models.DateField()
+    status = models.CharField(
+        max_length=20,
+        choices=(('option one', 'Option One'),
+                 ('option two', 'Option Two')))
+    slug1 = models.SlugField()
+    slug2 = models.SlugField()
+
+class RelatedPrepopulated(models.Model):
+    parent = models.ForeignKey(MainPrepopulated)
+    name = models.CharField(max_length=75)
+    pubdate = models.DateField()
+    status = models.CharField(
+        max_length=20,
+        choices=(('option one', 'Option One'),
+                 ('option two', 'Option Two')))
+    slug1 = models.SlugField(max_length=50)
+    slug2 = models.SlugField(max_length=60)
\ No newline at end of file

Modified: django/trunk/tests/regressiontests/admin_views/tests.py
===================================================================
--- django/trunk/tests/regressiontests/admin_views/tests.py     2012-02-19 
09:22:18 UTC (rev 17561)
+++ django/trunk/tests/regressiontests/admin_views/tests.py     2012-02-19 
16:42:12 UTC (rev 17562)
@@ -17,7 +17,8 @@
 from django.contrib.admin.sites import LOGIN_FORM_KEY
 from django.contrib.admin.util import quote
 from django.contrib.admin.views.main import IS_POPUP_VAR
-from django.contrib.auth import REDIRECT_FIELD_NAME, admin
+from django.contrib.admin.tests import AdminSeleniumWebDriverTestCase
+from django.contrib.auth import REDIRECT_FIELD_NAME
 from django.contrib.auth.models import Group, User, Permission, 
UNUSABLE_PASSWORD
 from django.contrib.contenttypes.models import ContentType
 from django.forms.util import ErrorList
@@ -40,7 +41,7 @@
     FoodDelivery, RowLevelChangePermissionModel, Paper, CoverLetter, Story,
     OtherStory, ComplexSortedPerson, Parent, Child, AdminOrderedField,
     AdminOrderedModelMethod, AdminOrderedAdminMethod, AdminOrderedCallable,
-    Report)
+    Report, MainPrepopulated, RelatedPrepopulated)
 
 
 ERROR_MESSAGE = "Please enter the correct username and password \
@@ -2892,6 +2893,110 @@
         response = 
self.client.get('/test_admin/admin/admin_views/prepopulatedpostlargeslug/add/')
         self.assertContains(response, "maxLength: 1000") # instead of 1,000
 
+
+class SeleniumPrePopulatedTests(AdminSeleniumWebDriverTestCase):
+    urls = "regressiontests.admin_views.urls"
+    fixtures = ['admin-views-users.xml']
+
+    def test_basic(self):
+        """
+        Ensure that the Javascript-automated prepopulated fields work with the
+        main form and with stacked and tabular inlines.
+        Refs #13068, #9264, #9983, #9784.
+        """
+        self.admin_login(username='super', password='secret', 
login_url='/test_admin/admin/')
+        self.selenium.get('%s%s' % (self.live_server_url,
+            '/test_admin/admin/admin_views/mainprepopulated/add/'))
+
+        # Main form ----------------------------------------------------------
+        
self.selenium.find_element_by_css_selector('#id_pubdate').send_keys('2012-02-18')
+        self.select_option('#id_status', 'option two')
+        self.selenium.find_element_by_css_selector('#id_name').send_keys(u' 
this is the mAin nÀMë and it\'s awεšome')
+        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-and-its-awesome-2012-02-18')
+        self.assertEqual(slug2, 'option-two-main-name-and-its-awesome')
+
+        # Stacked inlines ----------------------------------------------------
+        # Initial inline
+        
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-0-pubdate').send_keys('2011-12-17')
+        self.select_option('#id_relatedprepopulated_set-0-status', 'option 
one')
+        
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-0-name').send_keys(u'
 here is a sŤāÇkeð   inline !  ')
+        slug1 = 
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-0-slug1').get_attribute('value')
+        slug2 = 
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-0-slug2').get_attribute('value')
+        self.assertEqual(slug1, 'here-stacked-inline-2011-12-17')
+        self.assertEqual(slug2, 'option-one-here-stacked-inline')
+
+        # Add an inline
+        
self.selenium.find_element_by_css_selector('#relatedprepopulated_set-group 
.add-row a').click()
+        
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-pubdate').send_keys('1999-01-25')
+        self.select_option('#id_relatedprepopulated_set-1-status', 'option 
two')
+        
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-name').send_keys(u'
 now you haVe anöther   sŤāÇkeð  inline with a very ... 
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooog text... 
')
+        slug1 = 
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-slug1').get_attribute('value')
+        slug2 = 
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-slug2').get_attribute('value')
+        self.assertEqual(slug1, 
'now-you-have-another-stacked-inline-very-loooooooo') # 50 characters maximum 
for slug1 field
+        self.assertEqual(slug2, 
'option-two-now-you-have-another-stacked-inline-very-looooooo') # 60 characters 
maximum for slug2 field
+
+        # Tabular inlines ----------------------------------------------------
+        # Initial inline
+        
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-0-pubdate').send_keys('1234-12-07')
+        self.select_option('#id_relatedprepopulated_set-2-0-status', 'option 
two')
+        
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-0-name').send_keys(u'And
 now, with a tÃbűlaŘ inline !!!')
+        slug1 = 
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-0-slug1').get_attribute('value')
+        slug2 = 
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-0-slug2').get_attribute('value')
+        self.assertEqual(slug1, 'and-now-tabular-inline-1234-12-07')
+        self.assertEqual(slug2, 'option-two-and-now-tabular-inline')
+
+        # Add an inline
+        
self.selenium.find_element_by_css_selector('#relatedprepopulated_set-2-group 
.add-row a').click()
+        
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-pubdate').send_keys('1981-08-22')
+        self.select_option('#id_relatedprepopulated_set-2-1-status', 'option 
one')
+        
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-name').send_keys(u'a
 tÃbűlaŘ inline with ignored ;"&*^\%$#@-/`~ characters')
+        slug1 = 
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-slug1').get_attribute('value')
+        slug2 = 
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-slug2').get_attribute('value')
+        self.assertEqual(slug1, 'tabular-inline-ignored-characters-1981-08-22')
+        self.assertEqual(slug2, 'option-one-tabular-inline-ignored-characters')
+
+        # Save and check that everything is properly stored in the database
+        self.selenium.find_element_by_xpath('//input[@value="Save"]').click()
+        self.assertEqual(MainPrepopulated.objects.all().count(), 1)
+        MainPrepopulated.objects.get(
+            name=u' this is the mAin nÀMë and it\'s awεšome',
+            pubdate='2012-02-18',
+            status='option two',
+            slug1='main-name-and-its-awesome-2012-02-18',
+            slug2='option-two-main-name-and-its-awesome',
+        )
+        self.assertEqual(RelatedPrepopulated.objects.all().count(), 4)
+        RelatedPrepopulated.objects.get(
+            name=u' here is a sŤāÇkeð   inline !  ',
+            pubdate='2011-12-17',
+            status='option one',
+            slug1='here-stacked-inline-2011-12-17',
+            slug2='option-one-here-stacked-inline',
+        )
+        RelatedPrepopulated.objects.get(
+            name=u' now you haVe anöther   sŤāÇkeð  inline with a very ... 
loooooooooooooooooo', # 75 characters in name field
+            pubdate='1999-01-25',
+            status='option two',
+            slug1='now-you-have-another-stacked-inline-very-loooooooo',
+            
slug2='option-two-now-you-have-another-stacked-inline-very-looooooo',
+        )
+        RelatedPrepopulated.objects.get(
+            name=u'And now, with a tÃbűlaŘ inline !!!',
+            pubdate='1234-12-07',
+            status='option two',
+            slug1='and-now-tabular-inline-1234-12-07',
+            slug2='option-two-and-now-tabular-inline',
+        )
+        RelatedPrepopulated.objects.get(
+            name=u'a tÃbűlaŘ inline with ignored ;"&*^\%$#@-/`~ characters',
+            pubdate='1981-08-22',
+            status='option one',
+            slug1='tabular-inline-ignored-characters-1981-08-22',
+            slug2='option-one-tabular-inline-ignored-characters',
+        )
+
 class ReadonlyTest(TestCase):
     urls = "regressiontests.admin_views.urls"
     fixtures = ['admin-views-users.xml']

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to