From 706e542eb5db0d14277f34566d351b875e645bac Mon Sep 17 00:00:00 2001
From: Karen Tracey
Date: Sun, 21 Jul 2013 13:13:20 -0400
Subject: [PATCH] [1.6.x] Fixed #13696 -- ensured inline pk field is rendered
Backport of 3aad955ea8db1592fad0012155eaa25b72e50dc5 from master.
---
django/contrib/admin/helpers.py | 8 +++++---
.../templates/admin/edit_inline/stacked.html | 2 +-
.../templates/admin/edit_inline/tabular.html | 2 +-
tests/admin_inlines/admin.py | 20 ++++++++++++++++++-
tests/admin_inlines/models.py | 20 +++++++++++++++++++
tests/admin_inlines/tests.py | 18 +++++++++++++++++
6 files changed, 64 insertions(+), 6 deletions(-)
diff --git a/django/contrib/admin/helpers.py b/django/contrib/admin/helpers.py
index 320d3267a7..3ffb85e6c6 100644
--- a/django/contrib/admin/helpers.py
+++ b/django/contrib/admin/helpers.py
@@ -266,10 +266,12 @@ class InlineAdminForm(AdminForm):
yield InlineFieldset(self.formset, self.form, name,
self.readonly_fields, model_admin=self.model_admin, **options)
- def has_auto_field(self):
- if self.form._meta.model._meta.has_auto_field:
+ def needs_explicit_pk_field(self):
+ # Auto fields are editable (oddly), so need to check for auto or non-editable pk
+ if self.form._meta.model._meta.has_auto_field or not self.form._meta.model._meta.pk.editable:
return True
- # Also search any parents for an auto field.
+ # Also search any parents for an auto field. (The pk info is propagated to child
+ # models so that does not need to be checked in parents.)
for parent in self.form._meta.model._meta.get_parent_list():
if parent._meta.has_auto_field:
return True
diff --git a/django/contrib/admin/templates/admin/edit_inline/stacked.html b/django/contrib/admin/templates/admin/edit_inline/stacked.html
index 2025dd8083..32917756b3 100644
--- a/django/contrib/admin/templates/admin/edit_inline/stacked.html
+++ b/django/contrib/admin/templates/admin/edit_inline/stacked.html
@@ -13,7 +13,7 @@
{% for fieldset in inline_admin_form %}
{% include "admin/includes/fieldset.html" %}
{% endfor %}
- {% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
+ {% if inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
{{ inline_admin_form.fk_field.field }}
{% endfor %}
diff --git a/django/contrib/admin/templates/admin/edit_inline/tabular.html b/django/contrib/admin/templates/admin/edit_inline/tabular.html
index ca853bc989..e6097f0dce 100644
--- a/django/contrib/admin/templates/admin/edit_inline/tabular.html
+++ b/django/contrib/admin/templates/admin/edit_inline/tabular.html
@@ -29,7 +29,7 @@
{% if inline_admin_form.original %} {{ inline_admin_form.original }}{% endif %}
{% if inline_admin_form.show_url %}{% trans "View on site" %}{% endif %}
{% endif %}
- {% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
+ {% if inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
{{ inline_admin_form.fk_field.field }}
{% spaceless %}
{% for fieldset in inline_admin_form %}
diff --git a/tests/admin_inlines/admin.py b/tests/admin_inlines/admin.py
index 2f88248ca4..62f9e04e5b 100644
--- a/tests/admin_inlines/admin.py
+++ b/tests/admin_inlines/admin.py
@@ -12,8 +12,26 @@ class BookInline(admin.TabularInline):
model = Author.books.through
+class NonAutoPKBookTabularInline(admin.TabularInline):
+ model = NonAutoPKBook
+
+
+class NonAutoPKBookStackedInline(admin.StackedInline):
+ model = NonAutoPKBook
+
+
+class EditablePKBookTabularInline(admin.TabularInline):
+ model = EditablePKBook
+
+
+class EditablePKBookStackedInline(admin.StackedInline):
+ model = EditablePKBook
+
+
class AuthorAdmin(admin.ModelAdmin):
- inlines = [BookInline]
+ inlines = [BookInline,
+ NonAutoPKBookTabularInline, NonAutoPKBookStackedInline,
+ EditablePKBookTabularInline, EditablePKBookStackedInline]
class InnerInline(admin.StackedInline):
diff --git a/tests/admin_inlines/models.py b/tests/admin_inlines/models.py
index d4ba0ab6bc..dde5cf79e3 100644
--- a/tests/admin_inlines/models.py
+++ b/tests/admin_inlines/models.py
@@ -3,6 +3,7 @@ Testing of admin inline formsets.
"""
from __future__ import unicode_literals
+import random
from django.db import models
from django.contrib.contenttypes.models import ContentType
@@ -48,6 +49,25 @@ class Author(models.Model):
books = models.ManyToManyField(Book)
+class NonAutoPKBook(models.Model):
+ rand_pk = models.IntegerField(primary_key=True, editable=False)
+ author = models.ForeignKey(Author)
+ title = models.CharField(max_length=50)
+
+ def save(self, *args, **kwargs):
+ while not self.rand_pk:
+ test_pk = random.randint(1, 99999)
+ if not NonAutoPKBook.objects.filter(rand_pk=test_pk).exists():
+ self.rand_pk = test_pk
+ super(NonAutoPKBook, self).save(*args, **kwargs)
+
+
+class EditablePKBook(models.Model):
+ manual_pk = models.IntegerField(primary_key=True)
+ author = models.ForeignKey(Author)
+ title = models.CharField(max_length=50)
+
+
class Holder(models.Model):
dummy = models.IntegerField()
diff --git a/tests/admin_inlines/tests.py b/tests/admin_inlines/tests.py
index 41dc0e32de..465b224d4f 100644
--- a/tests/admin_inlines/tests.py
+++ b/tests/admin_inlines/tests.py
@@ -211,6 +211,24 @@ class TestInline(TestCase):
self.assertContains(response, max_forms_input % 2)
self.assertContains(response, total_forms_hidden)
+ def test_inline_nonauto_noneditable_pk(self):
+ response = self.client.get('/admin/admin_inlines/author/add/')
+ self.assertContains(response,
+ '',
+ html=True)
+ self.assertContains(response,
+ '',
+ html=True)
+
+ def test_inline_editable_pk(self):
+ response = self.client.get('/admin/admin_inlines/author/add/')
+ self.assertContains(response,
+ '',
+ html=True, count=1)
+ self.assertContains(response,
+ '',
+ html=True, count=1)
+
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
class TestInlineMedia(TestCase):