diff --git a/django/forms/forms.py b/django/forms/forms.py index ef9d657657..1b9faa7e4d 100644 --- a/django/forms/forms.py +++ b/django/forms/forms.py @@ -380,7 +380,10 @@ class BoundField(StrAndUnicode): if callable(data): data = data() else: - data = self.data + if isinstance(self.field, FileField) and self.data is None: + data = self.form.initial.get(self.name, self.field.initial) + else: + data = self.data if not only_initial: name = self.html_name else: diff --git a/tests/regressiontests/admin_views/models.py b/tests/regressiontests/admin_views/models.py index f1c24c2e99..211851f7b7 100644 --- a/tests/regressiontests/admin_views/models.py +++ b/tests/regressiontests/admin_views/models.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- +import tempfile +import os +from django.core.files.storage import FileSystemStorage from django.db import models from django.contrib import admin from django.core.mail import EmailMessage @@ -291,6 +294,27 @@ class EmptyModelAdmin(admin.ModelAdmin): class OldSubscriberAdmin(admin.ModelAdmin): actions = None +temp_storage = FileSystemStorage(tempfile.mkdtemp()) +UPLOAD_TO = os.path.join(temp_storage.location, 'test_upload') + +class Gallery(models.Model): + name = models.CharField(max_length=100) + +class Picture(models.Model): + name = models.CharField(max_length=100) + image = models.FileField(storage=temp_storage, upload_to='test_upload') + gallery = models.ForeignKey(Gallery, related_name="pictures") + +class PictureInline(admin.TabularInline): + model = Picture + extra = 1 + +class GalleryAdmin(admin.ModelAdmin): + inlines = [PictureInline] + +class PictureAdmin(admin.ModelAdmin): + pass + admin.site.register(Article, ArticleAdmin) admin.site.register(CustomArticle, CustomArticleAdmin) admin.site.register(Section, save_as=True, inlines=[ArticleInline]) @@ -306,6 +330,8 @@ admin.site.register(Podcast, PodcastAdmin) admin.site.register(Parent, ParentAdmin) admin.site.register(EmptyModel, EmptyModelAdmin) admin.site.register(Fabric, FabricAdmin) +admin.site.register(Gallery, GalleryAdmin) +admin.site.register(Picture, PictureAdmin) # We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2. # That way we cover all four cases: diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py index d7bce8fdcd..f8c790ef08 100644 --- a/tests/regressiontests/admin_views/tests.py +++ b/tests/regressiontests/admin_views/tests.py @@ -2,7 +2,9 @@ import re import datetime +import os +from django.core.files import temp as tempfile from django.test import TestCase from django.contrib.auth.models import User, Permission from django.contrib.contenttypes.models import ContentType @@ -13,7 +15,10 @@ from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME from django.utils.html import escape # local test models -from models import Article, CustomArticle, Section, ModelWithStringPrimaryKey, Person, Persona, FooAccount, BarAccount, Subscriber, ExternalSubscriber, Podcast, EmptyModel +from models import (Article, BarAccount, CustomArticle, EmptyModel, + ExternalSubscriber, FooAccount, Gallery, + ModelWithStringPrimaryKey, Person, Persona, Picture, + Podcast, Section, Subscriber) try: set @@ -1039,7 +1044,6 @@ class TestInlineNotEditable(TestCase): response = self.client.get('/test_admin/admin/admin_views/parent/add/') self.failUnlessEqual(response.status_code, 200) - class AdminCustomQuerysetTest(TestCase): fixtures = ['admin-views-users.xml'] @@ -1062,3 +1066,47 @@ class AdminCustomQuerysetTest(TestCase): self.assertEqual(response.status_code, 200) else: self.assertEqual(response.status_code, 404) + +class AdminInlineFileUploadTest(TestCase): + fixtures = ['admin-views-users.xml', 'admin-views-actions.xml'] + urlbit = 'admin' + + def setUp(self): + self.client.login(username='super', password='secret') + + # Set up test Picture and Gallery. + # These must be set up here instead of in fixtures in order to allow Picture + # to use a NamedTemporaryFile. + tdir = tempfile.gettempdir() + file1 = tempfile.NamedTemporaryFile(suffix=".file1", dir=tdir) + file1.write('a' * (2 ** 21)) + filename = file1.name + file1.close() + g = Gallery(name="Test Gallery") + g.save() + p = Picture(name="Test Picture", image=filename, gallery=g) + p.save() + + def tearDown(self): + self.client.logout() + + def test_inline_file_upload_edit_validation_error_post(self): + """ + Test that inline file uploads correctly display prior data (#10002). + """ + post_data = { + "name": u"Test Gallery", + "pictures-TOTAL_FORMS": u"2", + "pictures-INITIAL_FORMS": u"1", + "pictures-0-id": u"1", + "pictures-0-gallery": u"1", + "pictures-0-name": "Test Picture", + "pictures-0-image": "", + "pictures-1-id": "", + "pictures-1-gallery": "1", + "pictures-1-name": "Test Picture 2", + "pictures-1-image": "", + } + response = self.client.post('/test_admin/%s/admin_views/gallery/1/' % self.urlbit, post_data) + self.failUnless(response._container[0].find("Currently:") > -1) +