I have a database used by two different systems and as a result I actually need the FileField value to have a leading slash, like so:
/dirs/filename.ext
In Django, however, FileField values can't have a leading slash since it breaks how they interact with MEDIA_ROOT
.
So my suspicion is that I either have to create a custom storage class or somehow customize FileField so that the leading slash is stripped out when read and restored when saved.
In case anyone is wondering why I am doing this: I am mirroring the files on a separate non-Django server.
On the Django server, the files are relative to the media root. So supposing the media root was /path/to/myapp/media
, a file with the path dirs/filename.ext
would exist at /path/to/myapp/media/dirs/filename.ext
.
Meanwhile, when mirrored on the other server, they are stored relative to the webroot. So the path is equivalent to the absolute URL of the file (e.g. the file dirs/filename.ext
is stored in /path/to/example.com/dirs/filename.ext
and accessed as http://example.com/dirs/filename.ext
).
Both servers are using the same database.
I realize that one solution is prepending a slash everywhere the field is used on the other server, but that is across a number of different source files, whereas in Django thanks to the record model I should be able to make a change just in the models.py
file and it will work across the entire Django site.
So far I have tried creating a custom version of FileField
and it correctly prepends the /
on lookup and saving but I cannot get it to remove the leading slash when used within the Django app.
Imagine a record called Tool with a PDF file for its manual. On the Django server, it would be displayed in a template thusly:
<h1>{{ tool.name }}</h1>
<p>{{ tool.description }}</p>
<p><a href="{{ MEDIA_URL }}{{ tool.file.url }}">Link to Manual</a></p>
Meanwhile on the other server it's more like (this is CF code):
<h1>#GetTool.tool_name#</h1>
<p>#GetTool.tool_description#</p>
<p><a href="#GetTool.tool_file#">Link to Manual</a></p>
In the second server example, it needs to be an absolute URL.
So, to be clear:
Finally figured out how to do this. The trick was also subclassing FieldFile in addition to FileField:
class LeadingSlashFieldFile(files.FieldFile):
def __init__(self, instance, field, name):
name = re.sub(r'^/', '', name)
super(LeadingSlashFieldFile, self).__init__(instance, field, name)
class LeadingSlashFileField(models.FileField):
attr_class = LeadingSlashFieldFile
def get_prep_lookup(self, lookup_type, value):
if hasattr(value, 'name'):
value = value.name
if value[0] <> '/':
value = "/" + value
return super(LeadingSlashFileField, self).get_prep_lookup(lookup_type, value)
def get_prep_value(self, value):
value = super(LeadingSlashFileField, self).get_prep_value(value)
if value is None:
return None
value = unicode(value)
if value[0] <> '/':
value = "/" + value
return value
This appears to work.