Django: adding an “Add new” button for a ForeignKey in a ModelForm

前端 未结 3 1755
旧巷少年郎
旧巷少年郎 2020-12-01 08:30

TL;DR: How can I add an \"Add new\" button for a ForeignKey in a ModelForm?

Long version: I\'m using Django 1.7 for a project. I h

相关标签:
3条回答
  • 2020-12-01 08:40

    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))
    
    0 讨论(0)
  • 2020-12-01 08:48

    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))
    
    0 讨论(0)
  • 2020-12-01 08:51

    And to add to the RelatedFieldWidgetCanAdd functionality to directly add new value to the field add "?_to_field=id&_popup=1" to the url... thus in python3 (thanks to Cyril):

    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?_to_field=id&_popup=1" 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))
    
    0 讨论(0)
提交回复
热议问题