使用前导斜线存储Django FileField [英] Storing Django FileField with leading slash

查看:54
本文介绍了使用前导斜线存储Django FileField的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个供两个不同系统使用的数据库,因此,我实际上需要FileField值具有正斜杠,例如:

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

但是,在Django中,FileField值不能以斜线开头,因为它破坏了它们与 MEDIA_ROOT 的交互方式.

In Django, however, FileField values can't have a leading slash since it breaks how they interact with MEDIA_ROOT.

所以我的怀疑是我要么必须创建一个自定义存储类,要么以某种方式自定义FileField,以便在读取时删除前导斜线,并在保存时恢复该斜杠.

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.

万一有人想知道为什么要这样做:我正在将文件镜像到单独的 non -Django 服务器上.

In case anyone is wondering why I am doing this: I am mirroring the files on a separate non-Django server.

在Django服务器上,文件相对于媒体根目录.因此,假设媒体根目录为/path/to/myapp/media ,则路径为 dirs/filename.ext 的文件将存在于/path/to/myapp/media/dirs/filename.ext .

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.

同时,当在另一台服务器上进行镜像时,它们相对于Webroot存储.因此,该路径等效于文件的绝对URL(例如,文件 dirs/filename.ext 存储在/path/to/example.com/dirs/filename.ext ,并以 http://example.com/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.

我意识到一种解决方案是在其他服务器上使用该字段的任何地方都加一个斜杠,但这跨越了许多不同的源文件,而在Django中,由于我的记录模型,我应该只需在 models.py 文件中进行更改,它将在整个Django网站上正常工作.

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.

到目前为止,我已经尝试创建自定义版本的 FileField ,它正确地将/附加在查找并保存上,但是我无法获得它在Django应用中使用时,删除前导斜线.

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.

想象一下一个名为Tool的记录,其中包含PDF手册.在Django服务器上,它将因此显示在模板中:

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>

同时在另一台服务器上,它更像(这是CF代码):

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>

在第二个服务器示例中,它必须是一个绝对URL.

In the second server example, it needs to be an absolute URL.

因此,请明确说明:

  • 第二台服务器不是Django项目
  • 在第二台服务器上更改代码比在第一台服务器上更改要花费更多时间
  • 因此,FileField中的值必须是一个绝对URL,以便与Django兼容,但是需要与前导斜杠一起保存,以便与第二个服务器兼容.

推荐答案

最后弄清楚了如何做到这一点.诀窍还在于除了FileField之外,还继承了FieldFile:

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

这似乎起作用.

这篇关于使用前导斜线存储Django FileField的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆