我有一个电话模型(PhoneMixin - 用于任何其他模型)和Person:
from django.utils.translation import ugettext_lazy as _
from django.db import models
class PhoneMixin(models.Model):
TYPES_CHOICES = (
('HOME', u'Home'),
('WORK', u'Work'),
('MOBILE', u'Mobile'),
('HOME_FAX', u'Fax (home)'),
('WORK_FAX', u'Fax (work)'),
('PAGER', u'Pager'),
('OTHER', u'Other')
)
phone_type = models.CharField(_('Type'), max_length=20, choices=TYPES_CHOICES)
number = models.CharField(_('Number'), max_length=40)
comment = models.TextField(_('Comment'), blank=True, null=True)
class Person(models.Model):
class Meta:
verbose_name = u'Person'
verbose_name_plural = u'People'
name = models.CharField(max_length=255, verbose_name=u'Name')
email = models.EmailField(max_length=75)
def __unicode__(self):
return self.name
class PhonePerson(PhoneMixin):
belongs_to = models.ForeignKey(Person)
我也有自己的表格:
from django import forms
from models import Person, PhoneMixin
class PersonForm(forms.ModelForm):
class Meta:
model = Person
class PhoneForm(forms.ModelForm):
class Meta:
model = PhoneMixin
我唯一的观点是:
from django.forms.formsets import formset_factory
from django.http import HttpResponseRedirect
from django.shortcuts import render
from forms import PhoneForm, PersonForm
def person_insert_view(request):
PhoneFormset = formset_factory(PhoneForm)
if request.method == 'POST': # If the form has been submitted...
phone_formset = PhoneFormset(request.POST, prefix='phone_formset')
person_form = PersonForm(request.POST, prefix='person_form')
if person_form.is_valid(): # All validation rules pass
person = form.save(commit=False)
phone_formset = PhoneFormset(request.POST, instance=person)
if phone_formset.is_valid():
phone_formset.save()
person.save()
return HttpResponseRedirect('/') # Redirect after POST
else:
return render_to_response('function_based_person.html',{
'person_form': person_form,
'phone_formset': phone_formset,
})
else:
person_form = PersonForm()
phone_formset = PhoneFormset(prefix='phone_formset')
return render(request, 'function_based_person.html', {
'person_form': person_form,
'phone_formset': phone_formset,
})
和function_based_person.html模板:
<html>
<body>
<form enctype="multipart/form-data" method="post" action=".">
{% csrf_token %}
{% if person_form.visible_fields %}
{% for field in person_form.visible_fields %}
<div class="control-group{% if field.errors %} error{% endif %}">
<label class="control-label" for="id_{{ field.html_name }}">{{ field.label }} </label>
<div class="controls">
{{ field }}
{% if field.errors %}
<span class="help-inline">{% for error in field.errors %}{{ error }}{% endfor %}</span>
{% endif %}
{% if field.help_text %}<span class="help-inline">{{ field.help_text }}</span>{% endif %}
</div>
</div>
{% endfor %}
{% for phone_form in phone_formset %}
{{phone_form.as_table}}
{% endfor %}
<div class="form-actions">
<button type="submit" class="btn btn-primary">Save</button>
</div>
{% endif %}
</form>
</body>
</html>
问题是我想在我的Person中至少有一部手机,并且可能有2个或更多,用户想要添加它。
答案 0 :(得分:1)
ForeignKey只是指向另一个表中特定行的指针。你的Person
型号所说的是“每个人都有一两部电话。每部电话都存放在另一张叫做”电话“的桌子上。”
因此,除非您正在做一些复杂的事情,否则您的Person
表单会要求您将两个现有电话关联给您的新人。
(编辑以回复您的评论) 如果您想要的是拥有多部手机,那么您需要的是formset
您需要做的第一件事就是更改哪个表指向哪个:而不是指向电话的人,电话应该指向一个人。因此,例如,将belongs_to = models.ForeignKey(Person)
添加到您的手机型号声明中。
下一步是在视图中实际询问手机。这是formset的用武之地。在您的视图中,创建一个formset:
#in views.py
from django.forms.formsets import formset_factory
PhoneFormset = formset_factory(PhoneForm, extras = 1)
if request.method == 'POST':
phone_formset = PhoneFormset(request.POST, prefix = 'phone_formset')
person_form = PersonForm(request.POST, prefix='person_form')
# validate your forms, etc
else:
person_form = PersonForm()
phone_formset = PhoneFormset(prefix = 'phone_formset')
将phone_formset
添加到传递给模板的字典中,然后将其渲染为:
# in your template
<form>
{{person_form.as_p}}
{% for phone_form in phone_formset %}
{{phone_form.as_table}}
{% endfor %}
</form>
您需要做的最后一件事是将每个手机的belongs_to
字段设置为提交表单的人员。您必须在视图中执行此操作:可以在保存手机之前保存您的人,获取他们的PK,设置手机的外键然后保存。