Opened 10 years ago
Closed 10 years ago
#22999 closed Bug (invalid)
Impossible to generate migration for model with dynamic upload_to field
Reported by: | Owned by: | nobody | |
---|---|---|---|
Component: | Migrations | Version: | 1.7-rc-1 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
In my application I have a model which uploads forms to a specific user directory for better file system organization:
media_root/<username>/reports/file
To accomplish this, I use the following model:
upload_dir = upload_to_student_dir('committee/reports/') class CommitteeReport(TimeStampedModel): user = models.ForeignKey(User) document = models.FileField(upload_to=upload_dir)
The function defines and returns an inner function which will provide the complete path based on the instance's user:
def upload_to_student_dir(sub_path=''): def callable(instance, filename): """Dynamically returns the user directory to which this file should be uploaded. """ path = "students/{0}/{1}{2}".format(instance.user.username, sub_path, filename) return path return callable
Creating a migration via South seemed to have caused no problems, yet the analysis being employed by django.db.migrations differs and generates the following error:
Migrations for 'committee': 0001_initial.py: - Create model CommitteeReport Traceback (most recent call last): File "manage.py", line 11, in <module> execute_from_command_line(sys.argv) File "/home/kevin/.virtualenvs/stageportfolio/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line utility.execute() File "/home/kevin/.virtualenvs/stageportfolio/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 377, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/home/kevin/.virtualenvs/stageportfolio/local/lib/python2.7/site-packages/django/core/management/base.py", line 288, in run_from_argv self.execute(*args, **options.__dict__) File "/home/kevin/.virtualenvs/stageportfolio/local/lib/python2.7/site-packages/django/core/management/base.py", line 337, in execute output = self.handle(*args, **options) File "/home/kevin/.virtualenvs/stageportfolio/local/lib/python2.7/site-packages/django/core/management/commands/makemigrations.py", line 115, in handle self.write_migration_files(changes) File "/home/kevin/.virtualenvs/stageportfolio/local/lib/python2.7/site-packages/django/core/management/commands/makemigrations.py", line 143, in write_migration_files migration_string = writer.as_string() File "/home/kevin/.virtualenvs/stageportfolio/local/lib/python2.7/site-packages/django/db/migrations/writer.py", line 124, in as_string operation_string, operation_imports = OperationWriter(operation).serialize() File "/home/kevin/.virtualenvs/stageportfolio/local/lib/python2.7/site-packages/django/db/migrations/writer.py", line 76, in serialize arg_string, arg_imports = MigrationWriter.serialize(item) File "/home/kevin/.virtualenvs/stageportfolio/local/lib/python2.7/site-packages/django/db/migrations/writer.py", line 229, in serialize item_string, item_imports = cls.serialize(item) File "/home/kevin/.virtualenvs/stageportfolio/local/lib/python2.7/site-packages/django/db/migrations/writer.py", line 290, in serialize return cls.serialize_deconstructed(path, args, kwargs) File "/home/kevin/.virtualenvs/stageportfolio/local/lib/python2.7/site-packages/django/db/migrations/writer.py", line 205, in serialize_deconstructed arg_string, arg_imports = cls.serialize(arg) File "/home/kevin/.virtualenvs/stageportfolio/local/lib/python2.7/site-packages/django/db/migrations/writer.py", line 316, in serialize "Could not find function %s in %s.\nPlease note that " ValueError: Could not find function %s in %s. Please note that due to Python 2 limitations, you cannot serialize unbound method functions (e.g. a method declared and used in the same class body). Please move the function into the main module body to use migrations. For more information, see https://docs.djangoproject.com/en/1.7/topics/migrations/#serializing-values
As you can see I have already moved the function into the main module, yet the error persists.
What you've done is moving the function factory to the main module, as described by the exception message there's no way Django can reconstruct the returned inner function.
I suggest you define a callable factory class that implements
deconstruct
instead:This use to work with South because it didn't serialize the
upload_to
option of theFileField
and it subclasses.I'll mark as invalid since this is a well known limitation of the migration framework.