Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: override RelatedFieldWidgetWrapper

I want to change the way that the "+" icon for the foreign key in the admin site is shown.

I found that the widget that prints the code is RelatedFieldWidgetWrapper that is in django/contrib/admin/widgets.py.

So I wrote my version of this class and I changed its render function.

But now how can I use it? I mean... in the definition of my model do I have to use the formfield_overrides in this way?

formfield_overrides = {
        models.ForeignKey: {'widget': customRelatedFieldWidgetWrapper},
}

I think that this is not the right way, because that widget is not the one that manage the whole foreign key, but only the "+" icon. Am I wrong?

Thanks a lot.

like image 210
Giovanni Di Milia Avatar asked Jan 28 '10 16:01

Giovanni Di Milia


2 Answers

You would need to create custom ModelForm for ModelAdmin and override widget there.

Example code:

#forms.py
class CustomForm(forms.ModelForm):
    user = forms.ModelChoiceField(queryset=User.objects.all(), widget=yourCustomWidget)

class Meta:
    model = MyModel

#admin.py
class MyModelAdmin(admin.ModelAdmin):
     form = CustomForm
like image 192
Dmitry Shevchenko Avatar answered Oct 31 '22 14:10

Dmitry Shevchenko


I approached this slightly differently by monkey-patching the widget - that way the change is reflected in all forms and you're not monkeying around with django's source code.

I ran into this as I was working on customizing yawd admin, a very nice Twitter-Bootstrap skin for admin interface. Now all my icons are jazzed up.

import django.contrib.admin.widgets

class MyRelatedFieldWidgetWrapper(django.contrib.admin.widgets.RelatedFieldWidgetWrapper):
    """
    This class is a wrapper to a given widget to add the add icon for the
    admin interface.
    """
    def render(self, name, value, *args, **kwargs):
        rel_to = self.rel.to
        info = (rel_to._meta.app_label, rel_to._meta.model_name)
        self.widget.choices = self.choices
        output = [self.widget.render(name, value, *args, **kwargs)]
        if self.can_add_related:
            related_url = reverse(
                'admin:%s_%s_add' 
                % info, current_app=self.admin_site.name
            )
            output.append(
            """
            <a  href="%s"
                onclick="return showAddAnotherPopup(this);
                alt="%s">

                <i class="help icon-large icon-plus-sign"
                    id="add_id_%s"
                    data-original-title>
                </i>
            </a>""" % (related_url, _('Add Another'), name))
            return mark_safe(''.join(output))

# Monkeypatch it
django.contrib.admin.widgets.RelatedFieldWidgetWrapper = MyRelatedFieldWidgetWrapper
like image 44
synthesizerpatel Avatar answered Oct 31 '22 14:10

synthesizerpatel