Django多对多字段复制

时间:2011-08-07 06:07:48

标签: python django django-models many-to-many

我有一个包含2个多对多字段的Django模型。当我从管理界面保存模型时,我需要检查第二个字段是否为空白,如果它是空白的,那么我需要将第一个现场的项目复制到第二个。我怎么能这样做?

更新

马修的答案似乎很好用,但是在复制字段后我无法保存实例。我尝试过instance.save()但没有任何成功。

4 个答案:

答案 0 :(得分:3)

您可以使用保存后信号。这看起来可能是处理您需求的最佳方式:奖励是它也可以在管理员之外工作。

@models.signals.post_save(sender=MyModel)
def duplicate_missing_field(sender, instance, **kwargs):
    if not instance.my_second_m2m.count():
        instance.my_second_m2m.add(*instance.my_first_m2m.all())
        # or *instance.my_first_m2m.values_list('pk', flat=True), I think

我的代码可能不太正确:您需要阅读django中的信号。

答案 1 :(得分:3)

要使用的信号不是post_save,而是m2m_changed,在模型保存到数据库后发送的信号很多。

@models.signals.m2m_changed(sender=MyModel.second_m2m.through)
def duplicate_other_on_this_if_empty(sender, instance, action, reverse, model, pk_set, **kwargs):
    # just before adding a possibly empty set in "second_m2m", check and populate.
    if action == 'pre_add' and not pk_set:
        instance.__was_empty = True
        pk_set.update(instance.first_m2m.values_list('pk', flat=True))

@models.signals.m2m_changed(sender=MyModel.first_m2m.through)
def duplicate_this_on_other_if_empty(sender, instance, action, reverse, model, pk_set, **kwargs):
    # Just in case the "first_m2m" signals are sent after the other
    # so the actual "population" of the "second_m2m" is wrong:
    if action == 'post_add' and not pk_set and getattr(instance, '__was_empty'):
        instance.second_m2m = list(pk_set)
        delattr(instance, '__was_empty')

编辑:下一个代码更简单,并且基于对模型定义的新知识

在你的代码中,'first_m2m'信号在'second_m2m'之前发送(它实际上取决于你的模型定义)。因此,我们可以假设当收到'second_m2m'信号时,'first_m2m'已经填充了当前数据。

这让我们更开心,因为现在你只需要检查m2m-pre-add:

@models.signals.m2m_changed(sender=MyModel.second_m2m.through)
def duplicate_other_on_this_if_empty(sender, instance, action, reverse, model, pk_set, **kwargs):
    # just before adding a possibly empty set in "second_m2m", check and populate.
    if action == 'pre_add' and not pk_set:
        pk_set.update(instance.first_m2m.values_list('pk', flat=True))

答案 2 :(得分:0)

您可以覆盖clean方法以进行额外验证,因此如果第二个many2many为空,则可以设置默认值,例如:

def clean(self):
    super(MyClassModel, self).clean()

    if not self.MySecondMany2Many:
        # fill data

您应该在您的类中的models.py中设置此代码。如果clean不起作用,因为需要保存模型,你也可以覆盖保存功能,这是相同的过程。

我没有测试它,我认为你不能检查一个many2many字段是否空白,但你应该明白:)

答案 3 :(得分:0)

你可以从这里看到admin save override 定义,只需覆盖它并检查相关字段是否为空,如果是,保存对象,从第二个M2M获取相关数据并将其设置为第一个M2M并保存它再次......