Search code examples
djangodjango-formsdjango-admindjango-widget

Django: change admin FileField output?


I've made a model with file that is uploaded to custom path (not in MEDIA_ROOT). So it's some kind like protected file. Now I need to change it's representation in admin details. It shows a path relative to MEDIA_URL. I need to change that, to show a URL to an application view which generates a proper URL.

So, what is the best way to display link, and only in objects details in admin?


Solution

  • Here is the way I did it:

    models.py

    class SecureFile(models.Model):
        upload_storage = FileSystemStorage(
            location=settings.ABS_DIR('secure_file/files/'))
    
        secure_file = models.FileField(verbose_name=_(u'file'),
                                       upload_to='images', storage=upload_storage)
    

    widgets.py

    from django import forms
    from django.utils.translation import ugettext_lazy as _
    from django.core.urlresolvers import reverse
    from django.utils.safestring import mark_safe
    
    
    class AdminFileWidget(forms.FileInput):
        """A FileField Widget that shows secure file link"""
        def __init__(self, attrs={}):
            super(AdminFileWidget, self).__init__(attrs)
    
        def render(self, name, value, attrs=None):
            output = []
            if value and hasattr(value, "url"):
                url = reverse('secure_file:get_secure_file',
                              args=(value.instance.slug, ))
                out = u'<a href="{}">{}</a><br />{} '
                output.append(out.format(url, _(u'Download'), _(u'Change:')))
            output.append(super(AdminFileWidget, self).render(name, value, attrs))
            return mark_safe(u''.join(output))
    

    admin.py

    class SecureFileAdminForm(forms.ModelForm):
        def __init__(self, *args, **kwargs):
            super(SecureFileAdminForm, self).__init__(*args, **kwargs)
            self.fields['secure_file'].widget = AdminFileWidget()
    
        class Meta:
            model = SecureFile
    
    
    class SecureFileAdmin(admin.ModelAdmin):
        form = SecureFileAdminForm