1

我有一个代理模型。

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

我的经理中有这段代码:

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

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

4

1 回答 1

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 类中找到,当字段被深度复制时,该类对关系本身进行复制。我倾向于相信他们出于非常特定的原因实施了这种级别的复制,也许是为了阻止他们在做类似于你我试图添加一点魔法的事情时遇到的任何问题。所以也许我不会复制字典,而是执行深度复制,让 django 的深度复制实现做它需要的额外魔法。

除了这两个问题之外,我在将字段移动和复制到新模型类实例方面取得了很好的成功,我看不出你实现它的方式应该引起太多关注的“真正”原因。如果由于某种原因您遇到关系问题,至少您会知道从哪里开始:)

编辑

我创建了一个要点来帮助说明完整的实现:https ://gist.github.com/bmoyles0117/5604915

于 2013-05-18T04:48:42.453 回答