在表单集中访问多对多“通过”关系字段

Posted

技术标签:

【中文标题】在表单集中访问多对多“通过”关系字段【英文标题】:Accessing Many to Many "through" relation fields in Formsets 【发布时间】:2012-06-16 18:52:22 【问题描述】:

我的模特:

class End_User(models.Model):
    location = models.ForeignKey(Location) 
    first_name = models.CharField(max_length=70, blank=True, null=True)
    email_address = models.CharField(max_length=70, blank=True, null=True)

class Phone_Client(models.Model):
    end_user = models.ManyToManyField(End_User)
...
    extensions = models.CharField(max_length=20)

class Line(models.Model):
    phone_client = models.ManyToManyField(Phone_Client, through='Phone_Line' )
    ....
    voicemail = models.BooleanField(default=False)  

class Phone_Line(models.Model):
    phone_client = models.ForeignKey(Phone_Client)
    line = models.ForeignKey(Line)
    line_index = models.IntegerField()

所以基本上一个最终用户可以有很多电话,一个电话可以有很多线路,通过Phone_line相关。

我的页面需要让所有这些对象都可编辑,并且为 Phone_Clients 和 Line 创建运行时的新实例都在同一个页面中。目前我正在为 Phone_Client 和 Lines 创建一个简单的 End_User 模型表单和 modelformset_factory 对象。由于电话可以有很多行,所以 phone_formset 中的每个电话表单都可以有一个线路表单集对象。我目前正在做这样的事情

end_user = End_User.objects.get(pk=user_id)
user_form = End_UserForm(instance=end_user)

Phone_ClientFormSet = modelformset_factory(Phone_Client,form=PartialPhone_ClientForm,  extra=0, can_delete=True)

phone_clients_formset = Phone_ClientFormSet(queryset=end_user.phone_client_set.all(), prefix='phone_client')

all_lines = modelformset_factory(Line, form=PartialLineForm, extra=0, can_delete=True)

phone_clients = end_user.phone_client_set.all()

client_lines_formsets = 
for phone in phone_clients:
    client_lines_formsets[phone.id] = all_lines(queryset=phone.line_set.all(), prefix='phone_client_'+str(phone.id))

我正在使用此列表在模板中使用表单集显示属于 phone_client 的行。

我有以下关于模型的问题

    我可以使用 inline_formset 工厂来处理包含直通类的多对多关系吗?如果是这样,我该如何通过关系对 Phone_Client、Line 和 Phone_Line 执行此操作?

    我需要显示给定电话、线路组合的 line_index,如何在模板中执行此操作?我看过How do I access the properties of a many-to-many "through" table from a django template? 我不想只显示,而是将值绑定到电话、线路组合(如果可能)在线路或电话表单集中,这样如果用户更改索引,我可以在发布表单集数据时将其保存在数据库中。

我是 django 的新手,因此非常感谢任何帮助。 谢谢!!

【问题讨论】:

【参考方案1】:

您可能知道,您无法使用内联表单集编辑多对多关系。但是,您可以编辑直通模型。因此,对于您的内联表单集,您只需将模型设置为直通模型,例如:

inlineformset_factory(Phone_Client, Line.phone_client.through)

line_index 实际上是内联表单上的一个可见字段,所以你真的不需要做任何事情。如果有人更改了索引,它将在保存内联表单时被保存,就像其他字段一样。

【讨论】:

感谢您的回复。我会试试这个!! 我试过了,它对我有用。但是有一个问题,我必须分别处理 Line formset 和上面的 inline formset 对吗?? 我的意思是一个页面可以有多个电话,可以有多行,所以我在模板中处理这个逻辑。同样,我必须正确使用模板才能在行旁边显示 line_index? 内联内不能有内联。您可以与最终用户内联编辑电话,然后在另一个视图上编辑与电话内联的行。

以上是关于在表单集中访问多对多“通过”关系字段的主要内容,如果未能解决你的问题,请参考以下文章

具有多对多关系的Django表单不保存

Django内联表单集通过另一个模型在多对多关系中过滤

Hibernate - 从多对多关系访问字段

Django:通过另一个多对多关系访问多对多对象

在Django中按关系字段过滤多对多关系

通过 Django 中的模型表单保存多对多数据