Django:在 ModelForm 中为 ForeignKey 添加一个 "Add new" 按钮
Django: adding an "Add new" button for a ForeignKey in a ModelForm
TL;DR:如何在 ModelForm 中为外键添加 "Add new" 按钮?
长版:
我正在为一个项目使用 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 在为客户端字段添加下拉菜单方面做得非常好,用从客户端获取的条目填充它。不过,我希望有一个 "Add new client" link/button/whatever 来添加一个全新的客户,同时我添加一个相关的订单。
Django admin 会自动执行此操作,添加一个“+”按钮以打开弹出窗口,但我找不到像上面那样在 ModelForm 中执行此操作的简单方法。我在这里阅读了很多问题和链接其他地方,但对我没有任何帮助。对此有什么想法吗?
我已经在自定义小部件中解决了它。我不记得我是从 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')
将“+”按钮和 link 呈现到管理界面中的添加弹出窗口或您使用 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))
对于 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))
并添加到 RelatedFieldWidgetCanAdd 功能以直接向字段添加新值,将“?_to_field=id&_popup=1”添加到 url...
因此在 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))
TL;DR:如何在 ModelForm 中为外键添加 "Add new" 按钮?
长版: 我正在为一个项目使用 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 在为客户端字段添加下拉菜单方面做得非常好,用从客户端获取的条目填充它。不过,我希望有一个 "Add new client" link/button/whatever 来添加一个全新的客户,同时我添加一个相关的订单。
Django admin 会自动执行此操作,添加一个“+”按钮以打开弹出窗口,但我找不到像上面那样在 ModelForm 中执行此操作的简单方法。我在这里阅读了很多问题和链接其他地方,但对我没有任何帮助。对此有什么想法吗?
我已经在自定义小部件中解决了它。我不记得我是从 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')
将“+”按钮和 link 呈现到管理界面中的添加弹出窗口或您使用 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))
对于 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))
并添加到 RelatedFieldWidgetCanAdd 功能以直接向字段添加新值,将“?_to_field=id&_popup=1”添加到 url... 因此在 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))