Python Django:加上一个“;添加新的“;ModelForm中外键的按钮

Python Django:加上一个“;添加新的“;ModelForm中外键的按钮,python,django,django-forms,Python,Django,Django Forms,TL;DR:如何在模型表单中为外键添加“添加新”按钮 长版本: 我正在为一个项目使用Django 1.7。我的模型中有这两个模型。py class Client(models.Model): name = models.CharField(max_length=100) class Order(models.Model): code = models.IntegerField() client = models.ForeignKey(Client) [省略其他一些不相

TL;DR:如何在模型表单中为外键添加“添加新”按钮

长版本: 我正在为一个项目使用Django 1.7。我的模型中有这两个模型。py

class Client(models.Model):
    name = models.CharField(max_length=100)

class Order(models.Model):
    code = models.IntegerField()
    client = models.ForeignKey(Client)
[省略其他一些不相关的字段]

我使用ModelForm向db填充新订单,如下所示:

class OrderNewForm(forms.ModelForm):
    class Meta:
        model = Order
Django在为客户机字段添加下拉菜单方面做得相当好,它使用从客户机中获取的条目填充它。然而,我希望有一个“添加新客户”链接/按钮/任何东西,在添加相关订单的同时添加一个全新的客户


Django admin会自动执行此操作,并添加一个“+”按钮“这会打开一个弹出窗口,但我找不到一个简单的方法在上面的模型中实现这一点。我在这里读了很多问题和其他地方的链接,但没有什么真正帮助我。有什么想法吗?

我已经在一个自定义小部件中解决了这个问题。我不记得我是从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')
呈现“+”按钮并链接到管理界面中的添加弹出窗口或使用相关的_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))
从django.core.urlResolver反向导入
从django.utils.safestring导入标记_safe
从django.forms导入小部件
从django.conf导入设置
类RelatedFieldWidgetCanAdd(widgets.Select):
def uuu init uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
超级(相关字段widgetcanadd,self)。\uuuuuu初始值(*args,**kw)
如果与url不相关:
rel_to=相关_模型
info=(rel_to._meta.app_label,rel_to._meta.object_name.lower())
相关的\u url='管理员:%s\u%s\u添加“%info”
#注意此处不允许“反向”
self.related\u url=related\u url
def呈现(自身、名称、值、*args、**kwargs):
self.related\u url=反向(self.related\u url)
输出=[super(RelatedFieldWidgetCanAdd,self).render(名称、值、*args、**kwargs)]
output.append(u'%(settings.STATIC\u URL,u('Add other'))
返回标记_safe(u“”。连接(输出))
对于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))
class RelatedFieldWidgetCanAdd(widgets.Select):
def uuu init uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
超级(相关字段widgetcanadd,self)。\uuuuuu初始值(*args,**kw)
如果与url不相关:
rel_to=相关_模型
info=(rel_to._meta.app_label,rel_to._meta.object_name.lower())
相关的\u url='管理员:%s\u%s\u添加“%info”
#注意此处不允许“反向”
self.related\u url=related\u url
def呈现(自身、名称、值、*args、**kwargs):
self.related\u url=反向(self.related\u url)
输出=[super(RelatedFieldWidgetCanAdd,self).render(名称、值、*args、**kwargs)]
output.append(“”%(settings.STATIC_URL,'Add other'))
返回标记_safe(“”.join(输出))

要添加到相关字段WidgetCanAdd功能以直接向字段添加新值,请向url添加“?\u to\u field=id&\u popup=1”。。。 因此在python3中(感谢Cyril):

class RelatedFieldWidgetCanAdd(widgets.Select):
def uuu init uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
超级(相关字段widgetcanadd,self)。\uuuuuu初始值(*args,**kw)
如果与url不相关:
rel_to=相关_模型
info=(rel_to._meta.app_label,rel_to._meta.object_name.lower())
相关的\u url='管理员:%s\u%s\u添加“%info”
#注意此处不允许“反向”
self.related\u url=related\u url
def呈现(自身、名称、值、*args、**kwargs):
self.related\u url=反向(self.related\u url)
输出=[super(RelatedFieldWidgetCanAdd,self).render(名称、值、*args、**kwargs)]
output.append(“”%(settings.STATIC_URL,'Add other'))
返回标记_safe(“”.join(输出))

这是一个很好的提示,它就像一个符咒。我正在使用Python3,所以我需要一些非常小的调整来删除unicode和旧式的super,但这正是我所需要的。现在,我只需要在render()中进行更多调整,使其打开一个模式弹出窗口,并在添加新客户端后重新加载queryset。为此,我有一个问题,这段代码只显示属性名称等字段的名称,而不使用详细名称,并且我在代码中对3种语言使用国际化,知道如何使用标签的详细名称吗??谢谢隐马尔可夫模型。。。不确定问题是什么,对我来说,它将详细名称(可翻译)显示为字段标签,选择框本身,然后是带有“添加另一个”的+-图标,我希望详细名称将用于字段标签,就是这样。尝试更改字段的详细名称(不是相关模型),并检查它是否显示在字段标签中。。。
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))