Re: inlineformset_factory with a custom widget for a field

514 views
Skip to first unread message
Message has been deleted

panta

unread,
Dec 18, 2008, 2:30:10 PM12/18/08
to Django users
I've never used inlineformset_factory(), but I guess you can use the
formfield_callback parameter.
For example:

def my_formfield_cb(field):
if condition_on_field(field):
return SuitableFormField(widget = MyCustomWidget())
return field.formfield()

FileFormSet = inlineformset_factory(Version, File, extra=1,
formfield_callback=my_formfield_cb)

Cheers,
Marco

On Dec 18, 8:18 pm, Cortland Klein <cortl...@apple.com> wrote:
> I'm using inlineformset_factory in one of my views, which is working  
> great, except now I'd like to change the widget for one of the fields  
> (in case anyone's curious, an AdminFileWidget). For clarification this  
> is my own view and has nothing to do with contrib/admin.
>
> I see that inlineformset_factory has something for fields, but I'm not  
> sure what to pass to it to override a field's widget:
>
> # django/forms/models.py
>
> > def inlineformset_factory(parent_model, model, form=ModelForm,
> >                           formset=BaseInlineFormSet, fk_name=None,
> >                           fields=None, exclude=None,
> >                           extra=3, can_order=False, can_delete=True,  
> > max_num=0,
> >                           formfield_callback=lambda f: f.formfield()):
>
>  From my app:
>
> # models.py
>
> > class Version(models.Model):
> >    number = models.FloatField(_("Number"))
>
> > class File(models.Model):
> >    file       = models.FileField(_("File"), upload_to="materials/file/
> > %Y/%m/%d") # I want to eventually make this an AdminFileWidget
> >    version = models.ForeignKey(Version)
>
> # forms.py
>
> > from models import Version, File
> > from django.forms.models import inlineformset_factory
> > from django.contrib.admin.widgets import AdminFileWidget # Not sure  
> > how to get this into FileFormSet
>
> > FileFormSet = inlineformset_factory(Version, File, extra=1)
>
> # views.py
>
>
>
> > from forms import FileFormSet
> > from django.shortcuts import render_to_response
> > from django.template import RequestContext
>
> > def version(request, curriculum, version):
> >    response = {}
> >    if request.method == 'POST':
> >            response['fileformset']    = FileFormSet(request.POST,  
> > request.FILES, prefix="file", instance=response['version'])
> >            if response['fileformset'].is_valid():
> >                    response['fileformset'].save()
> >    else:
> >            response['fileformset']    = FileFormSet(prefix="file",  
> > instance=response['version'])
> >    return render_to_response('redacted/version.html', response,  
> > RequestContext(request))
>
> Any ideas?
>
> --
> Cortland Klein <cortl...@apple.com> +1 408 506 9791
> Web Developer, Media and Technology
> Apple Retail Training and Development
> 1 Infinite Loop, MS 49-SM
> Cupertino, CA 95014http://apple.com/retail/

panta

unread,
Dec 18, 2008, 2:53:08 PM12/18/08
to Django users
noticing you have provided also models.py, here is a more complete
answer:

def my_formfield_cb(field):
if isinstance(field, models.FileField) and field.name == 'file':
return fields.FileField(widget = AdminFileWidget(attrs={'url':
"/my/url/"}))
return field.formfield()

FileFormSet = inlineformset_factory(Version, File, extra=1,
formfield_callback = my_formfield_cb)
formSet = FileFormSet()

Daniel Roseman

unread,
Dec 18, 2008, 5:17:28 PM12/18/08
to Django users
On Dec 18, 7:18 pm, Cortland Klein <cortl...@apple.com> wrote:
> I'm using inlineformset_factory in one of my views, which is working  
> great, except now I'd like to change the widget for one of the fields  
> (in case anyone's curious, an AdminFileWidget). For clarification this  
> is my own view and has nothing to do with contrib/admin.
>
> I see that inlineformset_factory has something for fields, but I'm not  
> sure what to pass to it to override a field's widget:
>
> # django/forms/models.py
>
> > def inlineformset_factory(parent_model, model, form=ModelForm,
> >                           formset=BaseInlineFormSet, fk_name=None,
> >                           fields=None, exclude=None,
> >                           extra=3, can_order=False, can_delete=True,  
> > max_num=0,
> >                           formfield_callback=lambda f: f.formfield()):


Panta has given you one possibility, using the formfield_callback
parameter. An alternative is to define your own ModelForm subclass and
pass that in the form parameter.

class FileForm(forms.ModelForm):
file = forms.FileField(widget=AdminFileWidget)
class Meta:
model = File

FileFormSet = inlineformset_factory(Version, File, extra=1,
form=VersionForm)

--
DR.

Cortland Klein

unread,
Dec 18, 2008, 5:24:15 PM12/18/08
to django...@googlegroups.com
Yep that works, adding that and the following to forms.py:
> from django.forms import fields
> from django.db import models
--
--
Cortland Klein <m...@pixelcort.com> +1 408 506 9791
http://pixelcort.com/
2260 California Street #13
Mountain View, CA, USA 94040
Reply all
Reply to author
Forward
0 new messages