Repository: django-cms/django-filer

Issue:
[develop] automatically generated migrations require settings.FILER_IMAGE_MODEL
With #1000 any 3rd party app creating a migration that uses ``FilerImageField`` will create an entry like this in the migrations:

```
migrations.AlterField(
    model_name='article',
    name='featured_image',
    field=filer.fields.image.FilerImageField(on_delete=django.db.models.deletion.SET_NULL, verbose_name='featured image', blank=True, to=settings.FILER_IMAGE_MODEL, null=True),
),
```
And will fail to run because ``settings.FILER_IMAGE_MODEL`` is not set for most projects.
Is there a way to set a default for this value in settings?


Discussion:
@skirsdeda do you have advice on the issue?
@stefanfoulis First it would make sense to have `get_image_model` function (something like https://github.com/django/django/blob/master/django/contrib/auth/__init__.py#L188). Then `FilerImageField` should have `deconstruct` method which would just skip `to` kwarg so that it doesn't appear in migrations while field's constructor could deal with calling `get_image_model` and then providing it to `to` kwarg.
Thinking this over... Maybe it would be better if `deconstruct` had `to` with actual model name so that when `FILER_IMAGE_MODEL` setting changes, makemigrations would generate a new migration. After all, Django uses foreign key constraints at database level.

Resolving patch:
diff --git a/filer/fields/file.py b/filer/fields/file.py
--- a/filer/fields/file.py
+++ b/filer/fields/file.py
@@ -138,12 +138,3 @@ def formfield(self, **kwargs):
         }
         defaults.update(kwargs)
         return super(FilerFileField, self).formfield(**defaults)
-
-    def south_field_triple(self):
-        "Returns a suitable description of this field for South."
-        # We'll just introspect ourselves, since we inherit.
-        from south.modelsinspector import introspector
-        field_class = "django.db.models.fields.related.ForeignKey"
-        args, kwargs = introspector(self)
-        # That's our definition!
-        return (field_class, args, kwargs)
diff --git a/filer/settings.py b/filer/settings.py
--- a/filer/settings.py
+++ b/filer/settings.py
@@ -13,9 +13,13 @@
 
 logger = logging.getLogger(__name__)
 
-# This represents the actual Image model (as opposed to FILER_IMAGE_MODEL global setting which could be
-# undefined)
-FILER_IMAGE_MODEL = getattr(settings, 'FILER_IMAGE_MODEL', 'filer.Image')
+# FILER_IMAGE_MODEL setting is used to swap Image model.
+# If such global setting does not exist, it will be created at this point (with default model name).
+# This is needed especially when using this setting in migrations.
+if not hasattr(settings, 'FILER_IMAGE_MODEL'):
+    setattr(settings, 'FILER_IMAGE_MODEL', 'filer.Image')
+FILER_IMAGE_MODEL = settings.FILER_IMAGE_MODEL
+
 FILER_DEBUG = getattr(settings, 'FILER_DEBUG', False)  # When True makes
 FILER_SUBJECT_LOCATION_IMAGE_DEBUG = getattr(settings, 'FILER_SUBJECT_LOCATION_IMAGE_DEBUG', False)
 FILER_WHITESPACE_COLOR = getattr(settings, 'FILER_WHITESPACE_COLOR', '#FFFFFF')
diff --git a/filer/utils/loader.py b/filer/utils/loader.py
--- a/filer/utils/loader.py
+++ b/filer/utils/loader.py
@@ -42,14 +42,9 @@ def load_object(import_path):
 
 
 def load_model(model_name):
-    from django import VERSION as django_version
+    from django.apps import apps
 
     model_name_tuple = model_name.split('.')
-
-    if django_version[:2] < (1, 7):
-        from django.db.models import get_model
-        return get_model(*model_name_tuple)
-    from django.apps import apps
     return apps.get_model(*model_name_tuple)
 
 


Test patch:
diff --git a/filer/tests/models.py b/filer/tests/models.py
--- a/filer/tests/models.py
+++ b/filer/tests/models.py
@@ -12,6 +12,7 @@
 from ..models.clipboardmodels import Clipboard
 from ..models.filemodels import File
 from ..models.foldermodels import Folder
+from ..models.imagemodels import Image as DefaultImage
 from ..models.mixins import IconsMixin
 from ..settings import FILER_IMAGE_MODEL
 from ..test_utils import ET_2
@@ -252,7 +253,7 @@ def test_custom_model(self):
         Check that the correct model is loaded and save / reload data
         """
         image = self.create_filer_image()
-        if getattr(settings, 'FILER_IMAGE_MODEL', False):
+        if DefaultImage._meta.swapped:
             self.assertTrue(hasattr(image, 'extra_description'))
             self.assertFalse(hasattr(image, 'author'))
             image.extra_description = 'Extra'