How can I manually use RelatedFieldWidgetWrapper around a custom widget?

3,718 views
Skip to first unread message

justind

unread,
Mar 9, 2010, 4:25:05 PM3/9/10
to Django users
Hello,

I've created a custom widget to replace the many to many widget found
in the admin. Its working well, but I lose the "add" button when I use
it. I see that the functionality is added by wrapping the widget in
the RelatedFieldWidgetWrapper, but I can't figure out how to implement
it. Essentially, my problem is the same as the user Julien who wrote
to this group in 2007 under the subject "Popup 'add another' and
custom widget in newforms-admin". (Actually I'm having the secondary
problem he lists too, where form is still spitting back Validation
errors even though the model specifies that this field is blank=True
null=True)

I noticed this solution here: http://www.hoboes.com/Mimsy/hacks/replicating-djangos-admin/,
but it seems like using the built in RelatedFieldWidgetWrapper would
be the way to go to avoid any unexpected problems.

My Form code looks like this:

class EasyResourceAdminForm(forms.ModelForm):
files =
forms.ModelMultipleChoiceField(queryset=File.objects.none(),
widget=MySelect)

def __init__(self, *args, **kwargs):
super(EasyResourceAdminForm, self).__init__(*args, **kwargs)
self.fields['files'].queryset =
File.objects.filter(resource=self.instance.pk)

class Meta:
model = Resource

My AdminForm starts like this...

class ResourceAdmin(admin.ModelAdmin):
form = EasyResourceAdminForm

MySelect is a subclass of SelectMultiple and implements custom render
and render_options fields.

I tried watching the execution from PDB in a few places, but I get
lost quickly.

Any ideas?

Thanks,
Justin

justind

unread,
Mar 10, 2010, 10:55:48 AM3/10/10
to Django users
Hello,

I have this working now, but it seems so convoluted I know it must be
backwards or just plain dumb. I hope someone comes along and shows me
how easy this is.

First, I add the admin_site to the form field of my ModelAdmin object

class ResourceAdmin(admin.ModelAdmin):
form = EasyResourceAdminForm

def __init__(self, model, admin_site):
self.form.admin_site = admin_site
... # etc

Then in my ModelForm I manually create the relation and wrap the
widget. Like so...

class EasyResourceAdminForm(forms.ModelForm):
files =
forms.ModelMultipleChoiceField(queryset=File.objects.all(),
widget=MyWidget, required=False)

def __init__(self, *args, **kwargs):
super(EasyResourceAdminForm, self).__init__(*args, **kwargs)

# RelatedFieldWidgetWrapper wants a widget to wrap, a
relationship, and an admin site.
# The widget is easy. I build the relationship manually and
use the admin_site I added when the
# ModelAdmin was created.
rel = ManyToOneRel(self.instance.files.model, 'id')
self.fields['files'].widget =
admin.widgets.RelatedFieldWidgetWrapper(self.fields['files'].widget,
rel, self.admin_site)


self.fields['files'].queryset =
File.objects.filter(resource=self.instance.pk)

self.fields['files'].empty_label = None

Reply all
Reply to author
Forward
0 new messages