如何在Django的另一个模型中嵌入模型的表单?

时间:2013-07-19 11:03:20

标签: django forms model

使用Basti的回答视图更新

我有一个电话模型(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个或更多,用户想要添加它。

1 个答案:

答案 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,设置手机的外键然后保存。