我面对着无法遍历我的表单集的问题。 我已经在客户端模型(窗体)和电话模型(窗体集)之间创建了一个内联结构。我的目标是能够为每个客户存储多于一部电话。
问题在于,尽管我可以创建多个内联,但是在存储阶段,我的代码仅存储了最后一部电话,而不是预期的每部电话。 >
models.py
class Client(models.Model):
name = models.CharField(max_length=50, verbose_name="Όνομα")
surname = models.CharField(max_length=50, verbose_name="Επίθετο")
amka_amesa = models.BigIntegerField( validators=[MaxValueValidator(99999999999)],null=True,blank=True, verbose_name="AΜΚΑ Άμεσα Ασφαλισμένου")
amka_emesa = models.BigIntegerField( validators=[MaxValueValidator(99999999999)], unique=True, null=True, blank=True, verbose_name="ΑΜΚΑ Έμεσα Ασφαλισμένου")
am_asfa = models.CharField( max_length=11, validators=[RegexValidator(r'^\d+$')], null=True, blank=True, verbose_name="Α.Μητρώου Ασφαλισμένου")
address = models.CharField(max_length=100, null=True, blank=True, verbose_name="Διεύθυνση")
ika_branch = models.ForeignKey(Client_IKA_Branch, null=True, blank=True, verbose_name=u'Υποκατάστημα Ασφαλισμένου')
notes = models.CharField(max_length=100, null=True, blank=True, verbose_name="Σημειώσεις")
#active field=1
#inactive field=0
INACTIVE, ACTIVE = range(0, 2)
ACTIVITY_OPTIONS = (
(INACTIVE, 'Ανενεργός'),
(ACTIVE, 'Ενεργός'),
)
activity = models.IntegerField(choices=ACTIVITY_OPTIONS, null=True,default=ACTIVE)
class Phone(models.Model):
MOBILE, WORK, HOME = range(0, 3)
CATEGORIES = (
(MOBILE, 'Κινητό'),
(WORK, 'Δουλειά'),
(HOME, 'Σπίτι'),
)
number = models.CharField(max_length=14, null=True)
category = models.IntegerField(choices=CATEGORIES, null=True,default=MOBILE)
client = models.ForeignKey(Client, null=True)
def __unicode__(self):
return self.number
def get_absolute_url(self):
return reverse('client_list')
forms.py
class ClientForm(ModelForm):
class Meta:
model = Client
exclude=('activity',)
class PhoneForm(ModelForm):
class Meta:
model = Phone
exclude = ('client',)
ClientPhoneFormSet=inlineformset_factory(Client,Phone,form=PhoneForm,extra=1)
views.py
class ClientCreateView(LoginRequiredMixin, CreateView):
model = Client
form_class = ClientForm
template_name='test/test_client_phone.html'
def get_success_url(self):
return reverse('client_edit', args=(self.object.id,))
def form_valid(self, form):
ctx = self.get_context_data()
PhoneFormSet = ctx['PhoneFormSet']
if PhoneFormSet.is_valid() and form.is_valid():
self.object = form.save() # saves Father and Children
phones = PhoneFormSet.save(commit=False)
for instance in phones:
instance.save()
return redirect(self.get_success_url())
else:
return self.render_to_response(self.get_context_data(form=form))
def form_invalid(self, form):
return self.render_to_response(self.get_context_data(form=form))
def get_context_data(self, **kwargs):
ctx = super(ClientCreateView, self).get_context_data(**kwargs)
if self.request.POST:
ctx['form'] = ClientForm(self.request.POST)
ctx['PhoneFormSet'] = ClientPhoneFormSet(self.request.POST)
else:
ctx['form'] = ClientForm()
ctx['PhoneFormSet'] = ClientPhoneFormSet()
return ctx
模板
{% extends 'base.html' %}
{% load bootstrap3 %}
{% load static %}
<!-- Latest compiled and minified JavaScript -->
{% block content %}
<div class="col-md-12 text-center">
<h2>Δημιουργία / Αλλαγή Πελάτη </h2>
</div>
<hr>
<form class="well" method="post" action="">
{% csrf_token %}
{% bootstrap_form form %}
<table class="table phone">
{{ PhoneFormSet.management_form }}
{% for form in PhoneFormSet.forms %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tr class="{% cycle row1 row2 %} formset_row">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="{% static 'jquery.formset.js' %}"></script>
<script type="text/javascript">
$('table.phone tr.formset_row').formset({
addText: 'Πρόσθεσε Τηλέφωνο',
deleteText: 'Διαγραφή',
prefix: 'client_phone_set',
animateForms: true
});
</script>
{% buttons %}
<button type="submit" class="btn btn-primary">
Submit
</button>
{% endbuttons %}
</form>
<hr>
{{ form.media }}
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/forms.css' %}"/>
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/base.css' %}"/>
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/widgets.css' %}"/>
<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="/static/admin/js/core.js"></script>
<script type="text/javascript" src="/static/admin/js/admin/RelatedObjectLookups.js"></script>
<script type="text/javascript" src="/static/admin/js/vendor/jquery/jquery.min.js"></script>
<script type="text/javascript" src="/static/admin/js/jquery.init.js"></script>
<script type="text/javascript" src="/static/admin/js/actions.min.js"></script>
<script type="text/javascript" src="/static/admin/js/calendar.js"></script>
<script type="text/javascript" src="/static/admin/js/admin/DateTimeShortcuts.js"></script>
{% endblock %}
我注意到 phones = PhoneFormSet.save(commit = False)行仅返回一个实例。为什么会这样?
任何帮助将不胜感激。
答案 0 :(得分:0)
尝试更改
phones = PhoneFormSet.save(commit=False)
for instance in phones:
instance.save()
进入
phones = PhoneFormSet.save(commit=False)
phones.instance=self.object
phones.save()
答案 1 :(得分:0)
与模板中的前缀有关的修复。它必须是前缀:'phone_set',而不是像我以前那样的前缀:'client_phone_set'。