diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index 65653a6967..2eba1a2b93 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -638,9 +638,9 @@ class ModelAdmin(BaseModelAdmin): extra = '' if settings.DEBUG else '.min' js = [ 'core.js', - 'admin/RelatedObjectLookups.js', 'jquery%s.js' % extra, - 'jquery.init.js' + 'jquery.init.js', + 'admin/RelatedObjectLookups.js', ] if self.actions is not None: js.append('actions%s.js' % extra) diff --git a/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js b/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js index ffba7cdf24..d358b208f4 100644 --- a/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js +++ b/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js @@ -128,3 +128,12 @@ function dismissDeleteRelatedObjectPopup(win, objId) { // Kept for backward compatibility showAddAnotherPopup = showRelatedObjectPopup; dismissAddAnotherPopup = dismissAddRelatedObjectPopup; + +django.jQuery(function($){ + $(document).ready(function() { + $('.related-lookup').click(function(e) { + e.preventDefault(); + showRelatedObjectLookupPopup(this); + }); + }); +}); diff --git a/django/contrib/admin/templates/admin/change_form.html b/django/contrib/admin/templates/admin/change_form.html index 5e6c0c6321..cde7625c84 100644 --- a/django/contrib/admin/templates/admin/change_form.html +++ b/django/contrib/admin/templates/admin/change_form.html @@ -75,10 +75,6 @@ e.preventDefault(); showAddAnotherPopup(this); }); - $('.related-lookup').click(function(e) { - e.preventDefault(); - showRelatedObjectLookupPopup(this); - }); {% if adminform and add %} $('form#{{ opts.model_name }}_form :input:visible:enabled:first').focus() {% endif %} diff --git a/docs/releases/1.8.12.txt b/docs/releases/1.8.12.txt index 0052a90b0d..47581b3f19 100644 --- a/docs/releases/1.8.12.txt +++ b/docs/releases/1.8.12.txt @@ -15,3 +15,6 @@ Bugfixes * Fixed data loss on SQLite where ``DurationField`` values with fractional seconds could be saved as ``None`` (:ticket:`26324`). + +* Restored the functionality of the admin's ``raw_id_fields`` in + ``list_editable`` (:ticket:`26387`). diff --git a/tests/admin_views/admin.py b/tests/admin_views/admin.py index 68960dfbc1..8a980f45d5 100644 --- a/tests/admin_views/admin.py +++ b/tests/admin_views/admin.py @@ -33,16 +33,17 @@ from .models import ( GenRelReference, Grommet, ImplicitlyGeneratedPK, Ingredient, InlineReference, InlineReferer, Inquisition, Language, Link, MainPrepopulated, ModelWithStringPrimaryKey, NotReferenced, OldSubscriber, - OtherStory, Paper, Parent, ParentWithDependentChildren, Person, Persona, - Picture, Pizza, Plot, PlotDetails, PlotProxy, PluggableSearchPerson, - Podcast, Post, PrePopulatedPost, PrePopulatedPostLargeSlug, - PrePopulatedSubPost, Promo, Question, Recipe, Recommendation, Recommender, - ReferencedByGenRel, ReferencedByInline, ReferencedByParent, - RelatedPrepopulated, Report, Reservation, Restaurant, - RowLevelChangePermissionModel, Section, ShortMessage, Simple, Sketch, - State, Story, StumpJoke, Subscriber, SuperVillain, Telegram, Thing, - Topping, UnchangeableObject, UndeletableObject, UnorderedObject, - UserMessenger, Villain, Vodcast, Whatsit, Widget, Worker, WorkHour, + OtherStory, Paper, Parent, ParentWithDependentChildren, ParentWithUUIDPK, + Person, Persona, Picture, Pizza, Plot, PlotDetails, PlotProxy, + PluggableSearchPerson, Podcast, Post, PrePopulatedPost, + PrePopulatedPostLargeSlug, PrePopulatedSubPost, Promo, Question, Recipe, + Recommendation, Recommender, ReferencedByGenRel, ReferencedByInline, + ReferencedByParent, RelatedPrepopulated, RelatedWithUUIDPKModel, Report, + Reservation, Restaurant, RowLevelChangePermissionModel, Section, + ShortMessage, Simple, Sketch, State, Story, StumpJoke, Subscriber, + SuperVillain, Telegram, Thing, Topping, UnchangeableObject, + UndeletableObject, UnorderedObject, UserMessenger, Villain, Vodcast, + Whatsit, Widget, Worker, WorkHour, ) @@ -989,5 +990,13 @@ site.register(Group, GroupAdmin) site2 = admin.AdminSite(name="namespaced_admin") site2.register(User, UserAdmin) site2.register(Group, GroupAdmin) +site2.register(ParentWithUUIDPK) +site2.register( + RelatedWithUUIDPKModel, + list_display=['pk', 'parent'], + list_editable=['parent'], + raw_id_fields=['parent'], +) + site7 = admin.AdminSite(name="admin7") site7.register(Article, ArticleAdmin2) diff --git a/tests/admin_views/models.py b/tests/admin_views/models.py index 92182419c4..e5f6cc99f2 100644 --- a/tests/admin_views/models.py +++ b/tests/admin_views/models.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import datetime import os import tempfile +import uuid from django.contrib.auth.models import User from django.contrib.contenttypes.fields import ( @@ -909,3 +910,15 @@ class ReferencedByGenRel(models.Model): class GenRelReference(models.Model): references = GenericRelation(ReferencedByGenRel) + + +class ParentWithUUIDPK(models.Model): + id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + title = models.CharField(max_length=100) + + def __str__(self): + return str(self.id) + + +class RelatedWithUUIDPKModel(models.Model): + parent = models.ForeignKey(ParentWithUUIDPK, on_delete=models.CASCADE) diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index cb804dca8b..5b60368042 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -51,12 +51,12 @@ from .models import ( EmptyModel, FancyDoodad, FieldOverridePost, FilteredManager, FooAccount, FoodDelivery, FunkyTag, Gallery, Grommet, Inquisition, Language, Link, MainPrepopulated, ModelWithStringPrimaryKey, OtherStory, Paper, Parent, - ParentWithDependentChildren, Person, Persona, Picture, Pizza, Plot, - PlotDetails, PluggableSearchPerson, Podcast, Post, Promo, Question, - RelatedPrepopulated, Report, Restaurant, RowLevelChangePermissionModel, - Section, ShortMessage, Simple, Story, Subscriber, Telegram, Topping, - UnchangeableObject, UndeletableObject, UnorderedObject, Villain, Vodcast, - Whatsit, Widget, Worker, WorkHour, + ParentWithDependentChildren, ParentWithUUIDPK, Person, Persona, Picture, + Pizza, Plot, PlotDetails, PluggableSearchPerson, Podcast, Post, Promo, + Question, RelatedPrepopulated, RelatedWithUUIDPKModel, Report, Restaurant, + RowLevelChangePermissionModel, Section, ShortMessage, Simple, Story, + Subscriber, Telegram, Topping, UnchangeableObject, UndeletableObject, + UnorderedObject, Villain, Vodcast, Whatsit, Widget, Worker, WorkHour, ) @@ -4056,6 +4056,23 @@ class SeleniumAdminViewsFirefoxTests(AdminSeleniumWebDriverTestCase): self.assertEqual(Pizza.objects.count(), 1) self.assertEqual(Topping.objects.count(), 2) + def test_list_editable_raw_id_fields(self): + parent = ParentWithUUIDPK.objects.create(title='test') + parent2 = ParentWithUUIDPK.objects.create(title='test2') + RelatedWithUUIDPKModel.objects.create(parent=parent) + self.admin_login(username='super', password='secret', login_url=reverse('admin:index')) + change_url = reverse('admin:admin_views_relatedwithuuidpkmodel_changelist', current_app=site2.name) + self.selenium.get(self.live_server_url + change_url) + self.selenium.find_element_by_id('lookup_id_form-0-parent').click() + self.wait_for_popup() + self.selenium.switch_to.window(self.selenium.window_handles[-1]) + # Select "parent2" in the popup. + self.selenium.find_element_by_link_text(str(parent2.pk)).click() + self.selenium.switch_to.window(self.selenium.window_handles[0]) + # The newly selected pk should appear in the raw id input. + value = self.selenium.find_element_by_id('id_form-0-parent').get_attribute('value') + self.assertEqual(value, str(parent2.pk)) + class SeleniumAdminViewsChromeTests(SeleniumAdminViewsFirefoxTests): webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver'