mirror of
https://github.com/django/django.git
synced 2025-10-31 09:41:08 +00:00
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.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17562 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
@@ -26,7 +26,7 @@ from .models import (Article, Chapter, Account, Media, Child, Parent, Picture,
|
||||
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 CustomTemplateBooleanFieldListFilter(BooleanFieldListFilter):
|
||||
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(CoverLetter, CoverLetterAdmin)
|
||||
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:
|
||||
|
||||
@@ -575,3 +575,25 @@ class Report(models.Model):
|
||||
|
||||
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)
|
||||
@@ -17,7 +17,8 @@ from django.contrib.admin.models import LogEntry, DELETION
|
||||
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 @@ from .models import (Article, BarAccount, CustomArticle, EmptyModel, FooAccount,
|
||||
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 @@ class PrePopulatedTest(TestCase):
|
||||
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']
|
||||
|
||||
Reference in New Issue
Block a user