Source code for django_tables2.columns.filecolumn

import os

from django.db import models
from django.utils.html import format_html

from ..utils import AttributeDict
from .base import library
from .linkcolumn import BaseLinkColumn


[docs]@library.register class FileColumn(BaseLinkColumn): """ Attempts to render `.FieldFile` (or other storage backend `.File`) as a hyperlink. When the file is accessible via a URL, the file is rendered as a hyperlink. The `.basename` is used as the text, wrapped in a span:: <a href="/media/path/to/receipt.pdf" title="path/to/receipt.pdf">receipt.pdf</a> When unable to determine the URL, a ``span`` is used instead:: <span title="path/to/receipt.pdf" class>receipt.pdf</span> `.Column.attrs` keys ``a`` and ``span`` can be used to add additional attributes. Arguments: verify_exists (bool): attempt to determine if the file exists If *verify_exists*, the HTML class ``exists`` or ``missing`` is added to the element to indicate the integrity of the storage. text (str or callable): Either static text, or a callable. If set, this will be used to render the text inside the link instead of the file's ``basename`` (default) """ def __init__(self, verify_exists=True, **kwargs): self.verify_exists = verify_exists super().__init__(**kwargs) def get_url(self, value, record): storage = getattr(value, "storage", None) if not storage: return None return storage.url(value.name) def text_value(self, record, value): if self.text is None: return os.path.basename(value.name) return super().text_value(record, value)
[docs] def render(self, record, value): attrs = AttributeDict(self.attrs.get("span", {})) classes = [c for c in attrs.get("class", "").split(" ") if c] exists = None storage = getattr(value, "storage", None) if storage: # we'll assume value is a `django.db.models.fields.files.FieldFile` if self.verify_exists: exists = storage.exists(value.name) else: if self.verify_exists and hasattr(value, "name"): # ignore negatives, perhaps the file has a name but it doesn't # represent a local path... better to stay neutral than give a # false negative. exists = os.path.exists(value.name) or exists if exists is not None: classes.append("exists" if exists else "missing") attrs["title"] = value.name attrs["class"] = " ".join(classes) return format_html( "<span {attrs}>{text}</span>", attrs=attrs.as_html(), text=self.text_value(record, value), )
[docs] @classmethod def from_field(cls, field, **kwargs): if isinstance(field, models.FileField): return cls(**kwargs)