Django:添加"添加新" ModelForm中外键的按钮

时间:2015-01-21 13:13:55

标签: python django django-forms

TL; DR :如何添加"添加新" ModelForm中的ForeignKey按钮?

长版: 我正在使用Django 1.7进行项目。我的models.py

中有这两个模型
class Client(models.Model):
    name = models.CharField(max_length=100)

class Order(models.Model):
    code = models.IntegerField()
    client = models.ForeignKey(Client)

[其他一些不相关的字段被省略]

我正在使用ModelForm用新订单填充数据库,如下所示:

class OrderNewForm(forms.ModelForm):
    class Meta:
        model = Order

Django在为客户端字段添加下拉菜单方面做得非常出色,并使用从客户端获取的条目填充它。不过,我想要一个"添加新客户"链接/按钮/在添加相关订单的同时添加全新客户端的任何内容。

Django管理员会自动执行此操作,添加" +"按钮"这会打开一个弹出窗口,但我无法在上面的模型框架中找到一种简单的方法。我在这里阅读了许多问题,并在其他地方链接,但没有什有什么想法吗?

3 个答案:

答案 0 :(得分:10)

我已经在自定义小部件中解决了它。我不记得我是从Django管理员那里拿走了部件,还是从头开始构建。

所以表格将是:

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')

小部件,呈现“+”按钮并链接到管理界面中的添加弹出窗口,或链接到您使用related_url参数提供的自定义视图:

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))

答案 1 :(得分:2)

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))

答案 2 :(得分:0)

要添加到RelatedFieldWidgetCanAdd功能以直接向字段添加新值,请将“?___field = id&amp; _popup = 1”添加到网址中... 因此在python3中(感谢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))