Falcon
Falcon

Reputation: 3160

Display relative url in iframe

I've got a model that contains a relative url, something like "abc.html".

I want to display that relative url in an iframe of a view. The urls can be dynamic, they come and go so I don't think I can solve this via static files.

However, I am unable to get it to work, I think it might be my urlconf or something:

Here's my view:

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})

This is basically my view:

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

But the iframe will always display a 404 because Django tries to resolve the file not the way my app-directory is structured. In my app I've got the assets folder in which most assets live but I am unable to reference it. I think I cannot use collectstatic because those files will change during runtime and I couldn't get it to work as static files either.

Can you please lend me a helping hand? I just started out learning Django and this behaviour puzzles me. I guess it's related to the URLConf.

Maybe there's a way to derive the absolute url from the relative one for the iframe src.

Edit:

Code for the model (it's really that slim atm)

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

Upvotes: 2

Views: 2170

Answers (2)

apiguy
apiguy

Reputation: 5362

I can see a couple of issues with your approach here so let me point out what I can and see if I can come up with some advice to help you out.

It looks like the asset_path is pointing at a file on your server that you want to return, and that the files referenced are stored in a directory called asset. If you want to serve a file directly you're going to need to do that separately from Django. When you're developing you can tell django to serve those files directly by making sure they are beneath the url specified by the STATIC_URL setting in your settings.py. On a production web server you'll want to configure that webserver to handle those urls itself instead of sending them to django.

Because of how files are handled by django, you shouldn't have views configured to respond to urls under the STATIC_URL directory. So if you have files being served directly from /assets/ you should not have a view configured to respond to /assets/manage/ (for example). In your example and comments it appears that the view is handling:

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

and that you are asking the browser to combine that with:

../assetrepository/asset1.html

Which produces:

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

Which is not going to work because instead of serving the file directly, django is trying to find a view that matches that url (and failing).

Here's how I'd recommend setting it up, with some explanation.

Generally when maintaining records of file-like resources in an application like this, the location of the file is made up of (at least) 3 parts:

  1. The server or host the file is located on
  2. The path to the file's location
  3. The name of the file itself

In my experience, when it's time to scale you're likely going to be changing #1 and #2, but almost never #3. Because this is the case, it's generally a good idea to keep a reference to the file name itself in the database, but keep the other information in a configuration file or be able to retrieve it in some other way at runtime (perhaps from the request object).

consider this approach:

#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/'

Not only should this work fine (so long as you put your asset files in the /static/assets/assetrepository/ directory) but it will save you all kinds of headaches when you need to move the files to a dedicated file server or S3 to reduce the load on your app server.

Let me know if I've misunderstood your issue. Hope this has helped somewhat.

Upvotes: 1

ignoff
ignoff

Reputation: 1

If you want to serve static html file (asset1.html in this case), create 'assets' folder under static files directory:

yourproject/yourapp/static/assets/

Add django.contrib.staticfiles into your INSTALLED_APPS directory in settings.py. Change your assets_path entry in db field to represent something like this:

/static/assets/asset1.html

Done. For more info read django documentation on static files.

Upvotes: 0

Related Questions