python - example - Guardar formset con menú desplegable Foreignkey: IntegrityError XXX_id puede no ser NULL
modelchoicefield django (1)
Estoy intentando tener un formset donde cada formulario (PropertySelector) tiene un menú desplegable (PropertySelector.property) mientras que cada elemento de ese menú es ForeignKey referencia a otro modelo (Property).
De alguna manera, cuando intento enviar y guardar el formset, obtengo:
Exception Type: IntegrityError
Exception Value: testproj_propertyselector.property_id may not be NULL
¿Qué tiene de malo y cómo puedo evitarlo? Mi código completo está debajo. Gracias.
EDITAR: me parece un problema inline_formset (quizás MySQL también). Por favor, ayúdenme con la solución.
El proyecto se llama testproj y mi aplicación también se llama testproj.
Primero llenamos la Propiedad:
>>> from testproj.models import Property
>>> p = Property(name=''prop1'', basic=True)
>>> p.save()
>>> p = Property(name=''prop2'', basic=True)
>>> p.save()
models.py
from django.db import models
class PropertySet(models.Model):
name = models.CharField(max_length=50)
class Property(models.Model):
name = models.CharField(max_length=50)
basic = models.BooleanField()
def __unicode__(self):
return u''%s'' % (self.name)
class PropertySelector(models.Model):
property_set = models.ForeignKey(PropertySet)
title = models.CharField(max_length=50)
property = models.ForeignKey(Property)
forms.py
from django.forms import ModelForm, TextInput, Select, ModelChoiceField
from django.db.models import Q
from testproj.models import Property, PropertySet, PropertySelector
class PropertySetForm(ModelForm):
class Meta:
model = PropertySet
def PropertySelForm():
PropertyQueryset = Property.objects.filter(Q(basic=True))
class PropertySelectorForm(ModelForm):
property = ModelChoiceField(
queryset=PropertyQueryset,
widget=Select(attrs={''class'': ''property''})
)
def __init__(self, *args, **kwargs):
super(ModelForm, self).__init__(*args, **kwargs)
self.css_class = "prop_sel"
class Meta:
model = PropertySelector
fields = ("property_set", "title")
widgets = {"title" : TextInput(attrs={"class" : "title"})}
return PropertySelectorForm
views.py
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.forms.models import inlineformset_factory
from testproj.models import PropertySet, PropertySelector
from testproj.forms import PropertySetForm, PropertySelForm, PropertySelForm
def index(request):
property_selector_form = PropertySelForm()
PropertySelectorFormSet = inlineformset_factory(PropertySet, PropertySelector, form=property_selector_form)
if request.method == "POST":
property_set_form = PropertySetForm(request.POST)
if property_set_form.is_valid():
saved_property_set = property_set_form.save()
prop_sel_formset = PropertySelectorFormSet(request.POST, instance=saved_property_set)
if prop_sel_formset.is_valid():
prop_sel_formset.save()
else:
property_set_form = PropertySetForm()
prop_sel_formset = PropertySelectorFormSet()
return render_to_response(
"testproj/index.html",
{
"property_set_form": property_set_form,
"prop_sel_formset": prop_sel_formset
},
context_instance=RequestContext(request)
)
index.html (plantilla):
{% block content %}
<head>
</head>
<body>
<form method="post" action=""> {% csrf_token %}
{{ property_set_form.as_p }}
{{ prop_sel_formset.management_form }}
{% for form in prop_sel_formset %}
{{ form }}
{% endfor %}
<input type="submit" value="Submit">
</form>
</body>
{% endblock %}
El property_id
no se guarda porque no lo incluye en su form.Meta
. Deje los campos, y funciona:
def PropertySelForm():
PropertyQueryset = Property.objects.filter(Q(basic=True))
class PropertySelectorForm(ModelForm):
property = ModelChoiceField(
queryset=PropertyQueryset,
widget=Select(attrs={''class'': ''property''})
)
def __init__(self, *args, **kwargs):
super(ModelForm, self).__init__(*args, **kwargs)
self.css_class = "prop_sel"
class Meta:
model = PropertySelector
#fields = ("property_set", "title")
widgets = {"title" : TextInput(attrs={"class" : "title"})}
return PropertySelectorForm
Cambiaría el nombre de PropertySelForm
a property_selectorform_factory
, pero así soy yo. :)