| | 5 | class StorageBackendAgnosticFileField(FileField): |
| | 6 | """ |
| | 7 | Subclass of Django's `FileField` that allows for storage backends to optionally implement a function |
| | 8 | `generate_filename` through which they can generate filenames in a manner suitable for their storage mechanisms, |
| | 9 | rather than through Django's implementation which is hardwired to specific file systems. |
| | 10 | """ |
| | 11 | |
| | 12 | def parse_upload_to(self): |
| | 13 | """ |
| | 14 | Same as `FileField.get_directory_name`, but without the file system specifics. Allows for date formatting. |
| | 15 | |
| | 16 | Returns |
| | 17 | ------- |
| | 18 | str |
| | 19 | The parsed `upload_to` string. |
| | 20 | """ |
| | 21 | return force_text(datetime.datetime.now().strftime(force_str(self.upload_to))) |
| | 22 | |
| 6 | | # allow for customized filename generation |
| 7 | | if hasattr(self.storage, 'generate_filename'): |
| | 24 | """ |
| | 25 | Overrides the regular implementation by first checking of the storage backend doesn't already implement this |
| | 26 | logic. Otherwise, falls back to the traditional implementation. |
| | 27 | |
| | 28 | Parameters |
| | 29 | ---------- |
| | 30 | instance : object |
| | 31 | The model instance the current file is attached to. It's passed to the `upload_to` call when `upload_to` is |
| | 32 | callable. |
| | 33 | filename : str |
| | 34 | The filename, if any. |
| | 35 | |
| | 36 | Returns |
| | 37 | ------- |
| | 38 | str |
| | 39 | The newly generated and/or validated filename. |
| | 40 | """ |
| | 41 | if hasattr(self.storage, 'generate_filename') and callable(self.storage.generate_filename): |
| 11 | | |
| 12 | | filename = force_text(datetime.datetime.now().strftime(force_str(self.upload_to))) |
| 13 | | return self.storage.generate_filename(filename) |
| 14 | | |
| 15 | | # If upload_to is a callable, make sure that the path it returns is |
| 16 | | # passed through get_valid_name() of the underlying storage. |
| 17 | | if callable(self.upload_to): |
| 18 | | directory_name, filename = os.path.split(self.upload_to(instance, filename)) |
| 19 | | filename = self.storage.get_valid_name(filename) |
| 20 | | return os.path.normpath(os.path.join(directory_name, filename)) |