在iframe中显示相对网址

2 投票
2 回答
2098 浏览
提问于 2025-04-17 09:38

我有一个模型,里面包含一个相对网址,比如“abc.html”。

我想在一个视图的iframe中显示这个相对网址。因为这些网址是动态的,会不断变化,所以我觉得不能通过静态文件来解决这个问题。

但是,我一直没法让它正常工作,我觉得可能是我的网址配置有问题:

这是我的视图:

def detail(request, asset_id):
    asset = get_object_or_404(Asset, pk=asset_id)
    relative_path = asset.asset_path
    return render_to_response('html/detail.html', {'asset': asset, 'url': relative_path})

这基本上就是我的视图:

<iframe src="{{ url }}" />

但是,iframe总是显示404错误,因为Django试图按照我的应用目录结构去查找文件。在我的应用中,有一个assets文件夹,里面存放了大部分资源,但我无法引用它。我觉得我不能使用collectstatic,因为这些文件在运行时会变化,我也没法把它们当作静态文件来使用。

你能帮我一下吗?我刚开始学习Django,这种情况让我很困惑。我想这可能和网址配置有关。

也许有办法从相对网址推导出绝对网址,以便用于iframe的src。

编辑:

模型的代码(现在真的很简单)

class Asset(models.Model):
    name = models.CharField(max_length=100)
    asset_path = models.CharField(max_length=4096)
    creation_date = models.DateTimeField(auto_now=True)

    def __unicode__(self):
        return self.name

2 个回答

0

如果你想提供一个静态的 HTML 文件(这里是 asset1.html),首先在静态文件的目录下创建一个叫 'assets' 的文件夹:

yourproject/yourapp/static/assets/

接着,在 settings.py 文件中的 INSTALLED_APPS 列表里添加 django.contrib.staticfiles。然后,把数据库字段中的 assets_path 修改成类似这样的内容:

/static/assets/asset1.html

完成了。想了解更多信息,可以查看 Django 关于静态文件的文档

1

我看到你在这里的方法有几个问题,想跟你说说我的看法,并看看能不能给你一些建议。

看起来你提到的 asset_path 是指向你服务器上一个你想返回的文件,而这些文件存放在一个叫做 asset 的文件夹里。如果你想直接提供一个文件,你需要单独处理这个事情,而不是通过 Django。当你在开发时,可以通过确保这些文件在 STATIC_URL 设置指定的 URL 下面,告诉 Django 直接提供这些文件。在生产环境的服务器上,你需要配置这个服务器自己处理这些 URL,而不是把它们交给 Django。

由于 Django 处理文件的方式,你不应该让视图去响应 STATIC_URL 目录下的 URL。所以如果你有文件直接从 /assets/ 提供,你就不应该有视图去响应 /assets/manage/ 这样的请求(举个例子)。在你的例子和评论中,似乎视图正在处理:

http://127.0.0.1:8000/assets/something/

而你又请求浏览器把这个和:

../assetrepository/asset1.html

结合起来,这样就生成了:

http://127.0.0.1:8000/assets/assetrepository/asset1.html

这样是行不通的,因为 Django 不是直接提供这个文件,而是在尝试找到一个匹配这个 URL 的视图(结果失败了)。

我建议你这样设置,并给你一些解释。

一般来说,在像这样的应用中维护文件资源的记录时,文件的位置由(至少)三个部分组成:

  1. 文件所在的服务器或主机
  2. 文件位置的路径
  3. 文件本身的名称

根据我的经验,当需要扩展时,你可能会改变第 1 和第 2 部分,但几乎从来不会改变第 3 部分。因为这样,所以通常建议在数据库中保留文件名的引用,而把其他信息放在配置文件中,或者在运行时以其他方式获取(也许从请求对象中)。

考虑一下这种方法:

#models.py
class Asset(models.Model):
    name = models.CharField(max_length=100)
    asset_filename = models.CharField(max_length=4096)
    creation_date = models.DateTimeField(auto_now=True)

    def __unicode__(self):
        return self.name

#views.py
from urlparse import urljoin

def detail(request, asset_id):
    asset = get_object_or_404(Asset, pk=asset_id)
    asset_url = build_asset_url(request.get_host(), settings.ASSET_URL, asset.asset_filename)
    return render_to_response('html/detail.html', {'asset': asset, 'url': asset_url})

def build_asset_url(host, path, filename):
    """ Builds an absolute url to an asset located on the current server """ 
    url = "http://" % host
    url = urljoin(url, path)
    return urljoin(url, filename)

#settings.py
STATIC_URL = '/static/'
ASSET_URL = '/static/assets/assetrepository/'

只要你把资产文件放在 /static/assets/assetrepository/ 目录下,这样应该没问题,而且当你需要把文件移动到专用文件服务器或 S3 上以减轻应用服务器的负担时,这样做会省去很多麻烦。

如果我误解了你的问题,请告诉我。希望这些对你有帮助。

撰写回答