From c1f8d87bb0ac72b213bf31e672bd34c93bda6b18 Mon Sep 17 00:00:00 2001
From: Matthias Kestenholz <mk@feinheit.ch>
Date: Thu, 23 Jul 2020 01:38:31 +0200
Subject: [PATCH] Fixed #31812 -- Fixed FileField.model for fields defined in
 abstract models.

Regression in a93425a37f4defdb31d4ca96bb3bf6da21f0b5ce.
---
 django/db/models/fields/files.py     |  4 ++++
 tests/model_fields/test_filefield.py | 21 ++++++++++++++++++++-
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py
index b064202ee3..e10a5bb6d9 100644
--- a/django/db/models/fields/files.py
+++ b/django/db/models/fields/files.py
@@ -299,6 +299,10 @@ class FileField(Field):
             file.save(file.name, file.file, save=False)
         return file
 
+    def contribute_to_class(self, cls, name, **kwargs):
+        super().contribute_to_class(cls, name, **kwargs)
+        setattr(cls, self.attname, self.descriptor_class(self))
+
     def generate_filename(self, instance, filename):
         """
         Apply (if callable) or prepend (if a string) upload_to to the filename,
diff --git a/tests/model_fields/test_filefield.py b/tests/model_fields/test_filefield.py
index d4e70d6041..51e29f6d25 100644
--- a/tests/model_fields/test_filefield.py
+++ b/tests/model_fields/test_filefield.py
@@ -8,8 +8,9 @@ from pathlib import Path
 from django.core.files import File, temp
 from django.core.files.base import ContentFile
 from django.core.files.uploadedfile import TemporaryUploadedFile
-from django.db import IntegrityError
+from django.db import IntegrityError, models
 from django.test import TestCase, override_settings
+from django.test.utils import isolate_apps
 
 from .models import Document
 
@@ -147,3 +148,21 @@ class FileFieldTests(TestCase):
                         self.assertEqual(document.myfile.field, loaded_myfile.field)
                     finally:
                         document.myfile.delete()
+
+    @isolate_apps('model_fields')
+    def test_abstract_filefield_model(self):
+        """
+        FileField.model returns the concrete model for fields defined in an
+        abstract model.
+        """
+        class AbstractMyDocument(models.Model):
+            myfile = models.FileField(upload_to='unused')
+
+            class Meta:
+                abstract = True
+
+        class MyDocument(AbstractMyDocument):
+            pass
+
+        document = MyDocument(myfile='test_file.py')
+        self.assertEqual(document.myfile.field.model, MyDocument)