Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django : customizing FileField value while editing a model

I've got a model, with FileField. When I edit this model in a view, I want to change the "current" value of FileField which gets displayed in the view form. Let me explain.

models.py:

class DemoVar_model(models.Model):
    ...
    Welcome_sound=models.FileField(upload_to='files/%Y/%m/%d')

forms.py:

class DemoVar_addform(ModelForm):
    ...
    class Meta:
        model = DemoVar_model        

views.py:

soundform = DemoVar_addform(instance=ivrobj)
....
return render_to_response(template,{'soundform':soundform}, ....)

Now I want to edit this model in my view. When I look in browser, I see the form being displayed as

Welcome sound: Currently: welcome_files/2011/04/27/15_35_58_ojCompany.wav.mp3 
Change : <Choose File button>

I want to change this "Currently" value, which describes the whole path of the file as it exits on my server. I want to trim this string to just the filename without the path. How do I accomplish that?

like image 448
Neo Avatar asked Apr 27 '11 21:04

Neo


2 Answers

You need to override the ClearableFileInput that is currently used, to change the way it's displayed.

Here is the code of the new ShortNameFileInput which inherit from the default ClearableFileInput with just a change on the 19th line to only show the file name:

from django.forms.widgets import ClearableFileInput
import os
# missing imports
from django.utils.safestring import mark_safe
from cgi import escape
from django.utils.encoding import force_unicode

class ShortNameClarableFileInput(ClearableFileInput):
    def render(self, name, value, attrs=None):
        substitutions = {
            'initial_text': self.initial_text,
            'input_text': self.input_text,
            'clear_template': '',
            'clear_checkbox_label': self.clear_checkbox_label,
        }
        template = u'%(input)s'
        substitutions['input'] = super(ClearableFileInput, self).render(name, value, attrs)

        if value and hasattr(value, "url"):
            template = self.template_with_initial
            substitutions['initial'] = (u'<a href="%s">%s</a>'
                                        % (escape(value.url),
                                           escape(force_unicode(os.path.basename(value.url))))) # I just changed this line
            if not self.is_required:
                checkbox_name = self.clear_checkbox_name(name)
                checkbox_id = self.clear_checkbox_id(checkbox_name)
                substitutions['clear_checkbox_name'] = conditional_escape(checkbox_name)
                substitutions['clear_checkbox_id'] = conditional_escape(checkbox_id)
                substitutions['clear'] = CheckboxInput().render(checkbox_name, False, attrs={'id': checkbox_id})
                substitutions['clear_template'] = self.template_with_clear % substitutions

        return mark_safe(template % substitutions)

To use it in your form, you'll have to manually set the widget you want to use :

class DemoVar_addform(ModelForm):
    ...
    class Meta:
        model = DemoVar_model
        widgets = {
            'Welcome_sound': ShortNameClarableFileInput,
        }                    

That should do the trick.

like image 73
Guillaume Esquevin Avatar answered Oct 24 '22 20:10

Guillaume Esquevin


If you want an easier way and avoid to rewrite the render logic of the widget, you can do a little hack.

from os import path
from django import forms


class FormatString(str):

    def format(self, *args, **kwargs):
        arguments = list(args)
        arguments[1] = path.basename(arguments[1])
        return super(FormatString, self).format(*arguments, **kwargs)


 class ClearableFileInput(forms.ClearableFileInput):

     url_markup_template = FormatString('<a href="{0}">{1}</a>')

And then manually set the widget for the field.

class DemoVar_addform(ModelForm):

    class Meta:
        model = DemoVar_model
        widgets = {
            'Welcome_sound': ClearableFileInput,
        }   
like image 29
Dragos C Avatar answered Oct 24 '22 21:10

Dragos C