Django: adding an "Add new" button for a ForeignKey in a ModelForm
for python3:
class RelatedFieldWidgetCanAdd(widgets.Select):
def __init__(self, related_model, related_url=None, *args, **kw):
super(RelatedFieldWidgetCanAdd, self).__init__(*args, **kw)
if not related_url:
rel_to = related_model
info = (rel_to._meta.app_label, rel_to._meta.object_name.lower())
related_url = 'admin:%s_%s_add' % info
# Be careful that here "reverse" is not allowed
self.related_url = related_url
def render(self, name, value, *args, **kwargs):
self.related_url = reverse(self.related_url)
output = [super(RelatedFieldWidgetCanAdd, self).render(name, value, *args, **kwargs)]
output.append('<a href="%s" class="add-another" id="add_id_%s" onclick="return showAddAnotherPopup(this);"> ' % \
(self.related_url, name))
output.append('<img src="%sadmin/img/icon_addlink.gif" width="10" height="10" alt="%s"/></a>' % (settings.STATIC_URL, 'Add Another'))
return mark_safe(''.join(output))
I have solved it in a custom widget. I don't remember if I took parts from Django admin, or I have built from scratch.
So the form will be:
class OrderNewForm(forms.ModelForm):
client = forms.ModelChoiceField(
required=False,
queryset=Client.objects.all(),
widget=RelatedFieldWidgetCanAdd(Client, related_url="so_client_add")
)
class Meta:
model = Order
fields = ('code', 'client')
And the widget, that renders the "+" button and link to the add popup in the admin interface or to a custom view you provice with the related_url argument is:
from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe
from django.forms import widgets
from django.conf import settings
class RelatedFieldWidgetCanAdd(widgets.Select):
def __init__(self, related_model, related_url=None, *args, **kw):
super(RelatedFieldWidgetCanAdd, self).__init__(*args, **kw)
if not related_url:
rel_to = related_model
info = (rel_to._meta.app_label, rel_to._meta.object_name.lower())
related_url = 'admin:%s_%s_add' % info
# Be careful that here "reverse" is not allowed
self.related_url = related_url
def render(self, name, value, *args, **kwargs):
self.related_url = reverse(self.related_url)
output = [super(RelatedFieldWidgetCanAdd, self).render(name, value, *args, **kwargs)]
output.append(u'<a href="%s" class="add-another" id="add_id_%s" onclick="return showAddAnotherPopup(this);"> ' % \
(self.related_url, name))
output.append(u'<img src="%sadmin/img/icon_addlink.gif" width="10" height="10" alt="%s"/></a>' % (settings.STATIC_URL, _('Add Another')))
return mark_safe(u''.join(output))