如何将父字段添加到Django InlineFormSet?

时间:2019-09-06 21:35:02

标签: python django django-models django-forms

如何将 parent 字段添加到InlineFormSet

我的尝试:

models.py:

from django.db import models

class Parent(models.Model):
    parent_name = models.CharField(max_length=45)

class Child(models.Model):
    child_name = models.CharField(max_length=45)
    parent = models.ForeignKey(Parent, on_delete=models.CASCADE)

forms.py:

from .models import Parent, Child
from django import forms

FormSet = forms.inlineformset_factory(Parent, Child, 
          fields='__all__'
)

views.py:

from .models import Parent
from .forms import FormSet

def view(req):
    instance = Parent.objects.get(pk=1)
    form = FormSet(instance=instance)

这将显示Child中的所有字段,而Parent中的所有字段都不会显示。

2 个答案:

答案 0 :(得分:0)

我设法找到一种使用OneToOneField的解决方法,但是我仍然不知道如何使用ForeignKey关系来实现此目的。

如果您具有这样的父母/子女关系:

class Parent(models.Model):
    parent_name = models.CharField(max_length=45)

class Child(models.Model):
    child_name = models.CharField(max_length=45)
    parent = models.OneToOneField(Parent, on_delete=models.CASCADE, parent_link=True)

将密钥parent_link=True添加到OneToOneField将使您可以引用来自父级的列,就好像它们是子级的列一样。

例如:

c = Child.objects.get(id=1)
print(c.parent_name)

另外,请注意,以下功能与上述模型等效:

class Parent(models.Model):
    parent_name = models.CharField(max_length=45)

class Child(Parent):
    child_name = models.CharField(max_length=45)

这个概念也扩展到任何ModelForm的领域。

class SomeModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(SomeModelForm, self).__init__(*args, **kwargs)

    class Meta:
        model = Child
        fields = ('parent_name', 'child_name')

我尚未使用inlineformset_factory对此进行过测试,但是由于我们将Child模型视为Parent模型的扩展,因此无需告诉{{1 }}关于formset_factory模型,因此Parent是我们所需要的:

modelformset_factory

如果您不熟悉模型继承,我会签出official docs

答案 1 :(得分:0)

您需要创建一个单独的父模型表单,然后将其与ChildFormset一起通过上下文传递:

# forms.py

from .models import Parent, Child
from django import forms

ChildFormSet = forms.inlineformset_factory(Parent, Child, 
          fields='__all__'
)

class ParentForm(forms.ModelForm):
    class Meta:
    model = Parent
    fields = ('parent_name',)
# views.py

from .models import Parent, Child
from .forms import ChildFormSet, ParentForm

def view(request, parent_id):
    parent = Parent.objects.get(pk=parent_id)
    formset = ChildFormSet(queryset=Child.objects.filter(parent=parent))
    form = ParentForm(instance=parent)

    return render(request, 'some_template.html', {
        'form': form,
        'formset': formset
    })
{# some_template.html #}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form method="post">
        {{ form.as_p }}
        Children:
        {{ formset.as_p }}
        {% csrf_token %}
        <button type="submit">Save</button>
        </form>
    </body>
</html>