From 7e4677df4a9925a516e7e674f65d76a56d31a75c Mon Sep 17 00:00:00 2001 From: Mykola Kokalko Date: Sun, 3 Feb 2019 15:24:48 +0200 Subject: [PATCH] Fixed #29529 -- FilePathField path parameter now accepts a callable. --- django/db/models/fields/__init__.py | 2 +- docs/ref/models/fields.txt | 13 ++++++++++++ tests/model_fields/test_filepathfield.py | 26 ++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/model_fields/test_filepathfield.py diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index f32ce6462964d..dbe4031cf019b 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -1712,7 +1712,7 @@ def get_prep_value(self, value): def formfield(self, **kwargs): return super().formfield(**{ - 'path': self.path, + 'path': self.path() if callable(self.path) else self.path, 'match': self.match, 'recursive': self.recursive, 'form_class': forms.FilePathField, diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt index 1b572d8076cb0..c9a22ad273c36 100644 --- a/docs/ref/models/fields.txt +++ b/docs/ref/models/fields.txt @@ -868,6 +868,19 @@ directory on the filesystem. Has three special arguments, of which the first is Required. The absolute filesystem path to a directory from which this :class:`FilePathField` should get its choices. Example: ``"/home/images"``. + A callable (such as a function) can also be passed to dynamically set the + path at runtime:: + + def generate_path(): + return os.path.join(settings.LOCAL_FILE_DIR, '/images') + + file = models.FilePathField(path=generate_path) + + .. versionchanged:: 3.0 + + Older versions don't allow passing a callable. + + .. attribute:: FilePathField.match Optional. A regular expression, as a string, that :class:`FilePathField` diff --git a/tests/model_fields/test_filepathfield.py b/tests/model_fields/test_filepathfield.py new file mode 100644 index 0000000000000..a6fdccdce5709 --- /dev/null +++ b/tests/model_fields/test_filepathfield.py @@ -0,0 +1,26 @@ +import os.path + +from django.db.models import FilePathField +from django.test import TestCase + +PATH = os.path.dirname(os.path.abspath(__file__)) + + +def generate_path(): + return PATH + + +class FilePathFieldTests(TestCase): + + def test_string(self): + fp = FilePathField(path=PATH) + self.assertEqual(PATH, fp.path) + + def test_callable(self): + fp = FilePathField(path=generate_path) + self.assertEqual(PATH, fp.path()) + + def test_formfield(self): + fp = FilePathField(path=generate_path) + formfield = fp.formfield() + self.assertEqual(formfield.path, PATH)