如何将模型转换为其后代代理模型的实例

时间:2013-05-09 22:58:58

标签: python django django-models

我有代理模型。

现在我想从其父模型的给定实例转换为代理的实例。

我在我的经理中有这个代码:

def from_parent_user(self, user):
    instance = Member()
    single_fields = self.model._meta.fields
    for field in single_fields:
        setattr(instance, field.name, getattr(user, field.name))

    multiple_fields = self.model._meta.many_to_many
    for field in multiple_fields:
        setattr(instance, field.name, getattr(user, field.name).all())
    return instance

这很有用,但在复制多个字段时会产生大量查询。 所以它甚至比仅仅这样做更糟糕:

def from_parent_user(self, user):
    return self.get(pk=user.pk)

任何方法都可以复制关键字,缓存或其他东西的关系,并且完全避免进行任何查询?

我将在几乎所有请求中使用此方法:/

编辑:

这似乎有效:

def from_parent_user(self, user):
    member = Member()
    single_fields = self.model._meta.fields
    for field in single_fields:
        setattr(member, field.name, getattr(user, field.name))
    multiple_fields = self.model._meta.many_to_many
    for field in multiple_fields:
        # doing this scares me, I don't know if it is safe:
        getattr(member, field.name).__dict__.update(getattr(user, field.name).__dict__)
    return member

如果有人知道这对多对多经理是否安全,请发表评论/回答。

1 个答案:

答案 0 :(得分:1)

在查看Django的逻辑后,我对您的方法只有一些顾虑。我也使用类似于你正在做的事情,但我从模拟场的创建和关联到新的父模型类的自上而下的方法。

关注1:

if auto_created:
    self.creation_counter = Field.auto_creation_counter
    Field.auto_creation_counter -= 1
else:
    self.creation_counter = Field.creation_counter
    Field.creation_counter += 1

这是初始化字段时发生的逻辑,django会增加Field类的静态计数器。据我所知,它不应该在大图中对你产生负面影响,这是我在Field __init__方法中找到的唯一静态参考

关注2:

def __deepcopy__(self, memodict):
    # We don't have to deepcopy very much here, since most things are not
    # intended to be altered after initial creation.
    obj = copy.copy(self)
    if self.rel:
        obj.rel = copy.copy(self.rel)
    memodict[id(self)] = obj
    return obj

这个方法可以在Field类中找到,它在深度复制字段时对关系本身进行复制。我倾向于相信他们已经实现了这种级别的复制,这是出于一个非常特殊的原因,也许是为了阻止他们在做类似于你和我试图增加一点魔力的事情时遇到的任何问题。所以也许不是复制dicts,我会执行一个深层复制,让django的深拷贝实现做它需要的额外魔法。

除了这两个问题之外,我已经取得了很好的成功,并将字段复制到新的模型类实例中,我认为没有“真正的”理由说明为什么实现它的方式应引起太多关注。如果由于某种原因你遇到了关系问题,至少你会知道从哪里开始:)

修改

我已经创建了一个要点,以帮助说明完整的实施:https://gist.github.com/bmoyles0117/5604915