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.
--
Ticket URL: <https://code.djangoproject.com/ticket/22999>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* status: new => closed
* needs_better_patch: => 0
* resolution: => invalid
* needs_tests: => 0
* needs_docs: => 0
Comment:
> The function defines and returns an inner function which will provide
the complete path based on the instance's user...
> 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:
{{{#!python
from django.utils.deconstruct import deconstructible
@deconstructible
class UploadToStudentDir(object):
path = "students/{0}/{1}{2}"
def __init__(self, sub_path):
self.sub_path = sub_path
def __call__(self, instance, filename):
return path.format(instance.user.username, self.sub_path,
filename)
upload_dir = UploadToStudentDir('committee/reports/')
}}}
This use to work with South because it didn't ''serialize'' the
`upload_to` option of the `FileField` and it subclasses.
I'll mark as invalid since this is a well known limitation of the
migration framework.
--
Ticket URL: <https://code.djangoproject.com/ticket/22999#comment:1>