python - formularios - submit django form
Django: agregar un botón "Agregar nuevo" para un ForeignKey en un ModelForm (3)
Lo he resuelto en un widget personalizado. No recuerdo si tomé partes del administrador de Django, o si he construido desde cero.
Así que la forma será:
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'')
Y el widget, que muestra el botón "+" y el enlace a la ventana emergente de agregar en la interfaz de administración o a una vista personalizada que proporcione con el argumento related_url es:
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))
TL; DR : ¿Cómo puedo agregar un botón "Agregar nuevo" para un ForeignKey en un ModelForm?
Versión larga : estoy usando Django 1.7 para un proyecto. Tengo estos dos modelos en mis modelos.
class Client(models.Model):
name = models.CharField(max_length=100)
class Order(models.Model):
code = models.IntegerField()
client = models.ForeignKey(Client)
[se omiten algunos otros campos no relevantes]
Estoy usando un ModelForm para rellenar la base de datos con nuevos pedidos, como este:
class OrderNewForm(forms.ModelForm):
class Meta:
model = Order
Django hace un buen trabajo al agregar un menú desplegable para el campo del cliente, llenándolo con entradas tomadas del Cliente. Sin embargo, me gustaría tener un vínculo / botón "Agregar nuevo cliente" / lo que sea para agregar un nuevo cliente al mismo tiempo que agrego una Orden relacionada.
El administrador de Django hace eso automáticamente, agregando un "+" botón "que abre una ventana emergente, pero no pude encontrar una manera fácil de hacerlo en un ModelForm como el de arriba. Leí muchas preguntas aquí y enlaces en otros lugares, pero nada realmente Me ayudó. ¿Alguna idea sobre eso?
Y para agregar a la funcionalidad RelatedFieldWidgetCanAdd para agregar directamente un nuevo valor al campo, agregue "? _To_field = id & _popup = 1" a la url ... así en python3 (gracias a 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))
para 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))