如何使用manyToMany和inlineformset在Django中表示家庭关系?

时间:2019-03-05 15:20:47

标签: django django-models django-templates manytomanyfield

我想创建一个更新视图,其中Person模型在模板中将其相关FamilyMember作为inlineformset。

在我的model.py中,我有:

ch[i] = 'A';

在我的form.py中,我有:

@NodeEntity

在我的view.py中,我有:

class Person(models.Model):
    Name = models.CharField(max_length=50)

class FamilyMember(models.Model):
    person = models.ManyToManyField(Person, through='PersonFamilyMember')
    relationType= models.CharField(max_length=3, choices=FAMILYRELATION_CHOICE)

class PersonFamilyMember(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    related = models.ForeignKey(FamilyMember, on_delete=models.CASCADE)

在我的模板中,我有:

class PersonForm(ModelForm):
    class Meta:
        model = Person
        fields = '__all__'

class FamilyMemberForm(ModelForm):
    class Meta:
        model = FamilyMember
        fields = '__all__'

RelatedFMFormSet = inlineformset_factory(Person, PersonFamilyMember.useCase.through,                                          form=FamilyMemberForm, can_delete=True, extra=1)

使用上面的代码段,渲染模板时,我会得到(请参见链接1中的图片:

结果,我无法单击相关的下拉列表来选择相关的人。另外,相关类型也不会显示在模板中。

1 个答案:

答案 0 :(得分:0)

您需要两个模型,而不是3个模型,因为您实际上是在将一个人与一个人相关联。

class RunStart(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        label = ttk.Label(self, text='ENDPOINT SYSTEM', font=LARGE_FONT)
        label.pack(padx=10, pady=10)

        abort_button = tk.Button(self, # This "ABORT" button should be able to be pressed at any time to terminate the function and call the parent frame StartPage
                        text="ABORT", 
                        font=('century gothic', 24),
                        bg='red', 
                        fg='white', 
                        height=1,
                        width=17,
                        relief='raised',
                        command=lambda: controller.show_frame(StartPage)
                        )
        abort_button.pack(pady=10, padx=10)

        start_find_endpoint() # This function should start running when the frame is called.

请注意,这种关系不是对称的。现在,如果您有<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/> <div id="video-play" class="container-fluid h-100"> <div class="row"> <div class="col d-flex justify-content-center"> <a href="#" class="video" data-video="https://www.youtube.com/watch?time_continue=1&v=wKc5SSzB4xY" data-toggle="modal" data-target="#videoModal"> <i class="far fa-play-circle fa-5x"></i> </a> </div> </div> <div class="row"> <div class="col"> <div class="row justify-content-center mt-3"> <a href="#" class="btn btn-outline-dark btn-lg">Learn More</a> </div> <div class="row justify-content-center mt-3"> <a href="#" class="btn btn-outline-dark btn-lg">Learn More</a> </div> </div> </div> </div>并且class Person(Model): name = ... family_members = ManyToManyField('self', through=FamilyMemberRelationship, through_fields=('person', 'relation')) class FamilyMemberRelationship(Model): person = ForeignKey(Person, on_delete=CASCADE, related_name='relationships') related = ForeignKey(Person, on_delete=CASCADE, related_name='reverse_relationships') relation_type = CharField(max_length=3, choices=FAMILYRELATION_CHOICE) 是Phil的兄弟,那么您可以这样做:

phil

这里唯一的是,relationship_type具有方向(不对称),因此您不能:

james

但是您可以:

relation = FamilyMemberRelationship(person=phil, related=james, relation_type='brother')
relation.save()
phil.family_members.all()  # james
phil.relations.filter(related=james).first().relation_type  # "brother" 
james.family_members.all()  # phil

您可能还想保存一个james.relations.filter(related=phil).first() # None ,以便在james.reverse_relations.filter(related=phil).first().relation_type # "brother" 是女孩的情况下可以在那里“姐姐”。