在Django中将模型对象从模型复制到另一个模型

时间:2012-05-30 13:34:38

标签: django django-models

我必须建模。我想将模型对象从模型复制到另一个: Model2是Model1的副本(此模型有太多m2m字段) 型号1:

class Profile(models.Model):
      user = models.OneToOneField(User)
      car = models.ManyToManyField(Car)
      job = models.ManyToManyField(Job)
      .
      .

这是一项调查申请。我想在他/她参加调查时保存用户的个人资料(因为他可以在调查后编辑个人资料) 我在调查时创建了另一个模型来保存用户档案(我不确定它的正确方法)

class SurveyProfile(models.Model):
      user = models.OneToOneField(SurveyUser) #this is another model that takes survey users
      car = models.ManyToManyField(Car)
      job = models.ManyToManyField(Job)

如何将用户个人资料从个人资料复制到SurveyProfile。

提前致谢

5 个答案:

答案 0 :(得分:10)

deepcopy等不起作用,因为类/模型不同。

如果您确定SurveyProfile包含Profile *中的所有字段,则应该有效(未经过测试):

for field in instance_of_model_a._meta.fields:
    if field.primary_key == True:
        continue  # don't want to clone the PK
    setattr(instance_of_model_b, field.name, getattr(instance_of_model_a, field.name))
instance_of_model_b.save()

*(在这种情况下,我建议您创建一个抽象的ProfileBase类,并将其作为ProfileSurveyProfile的具体类继承,但这不是影响我上面提到的内容)

答案 1 :(得分:3)

我很难理解你上面写的内容,因此我不能100%肯定这是否有效,但我认为我会做的就是这样,如果我理解你的话: / p>

class Model2Form(ModelForm):
    class Meta:
        model = models.Model2

然后

f = Model2Form(**m1.__dict__)
if f.is_valid():
    f.save()

但我认为这看起来更像是糟糕的数据库设计,而不是看到整个模型1我无法确定。但是,无论如何,我不确定你为什么要这样做,当你可以在模型级别使用继承或其他东西来获得相同的行为时。

答案 2 :(得分:2)

这是我一直在使用的功能,它建立在model_to_dict之上。 Model_to_dict只返回外键的ID而不是它们的实例,所以对于那些我用模型本身替换它们。

def update_model(src, dest):
    """
    Update one model with the content of another.

    When it comes to Foreign Keys, they need to be
    encoded using models and not the IDs as
    returned from model_to_dict.

    :param src: Source model instance.
    :param dest: Destination model instance.
    """
    src_dict = model_to_dict(src, exclude="id")
    for k, v in src_dict.iteritems():
        if isinstance(v, long):
            m = getattr(src, k, None)
            if isinstance(m, models.Model):
                setattr(dest, k, m)
                continue

        setattr(dest, k, v)

答案 3 :(得分:0)

我就是这样做的(注意:这是在Python3中,你可能需要改变一些东西 - 摆脱字典理解 - 如果你使用的是python 2):

def copy_instance_kwargs(src, exclude_pk=True, excludes=[]):
    """
    Generate a copy of a model using model_to_dict, then make sure
    that all the FK references are actually proper FK instances.  
    Basically, we return a set of kwargs that may be used to create
    a new instance of the same model - or copy from one model
    to another.

    The resulting dictionary may be used to create a new instance, like so:

    src_dict = copy_instance_kwargs(my_instance)
    ModelClass(**src_dict).save()

    :param src: Instance to copy
    :param exclude_pk: Exclude the PK of the model, to ensure new records are copies.
    :param excludes: A list of fields to exclude (must be a mutable iterable) from the copy. (date_modified, for example)
    """
    # Exclude the PK of the model, since we probably want to make a copy.
    if exclude_pk:
        excludes.append(src._meta.pk.attname)
    src_dict = model_to_dict(src, exclude=excludes)
    fks={k: getattr(src, k) for k in src_dict.keys() if 
         isinstance(getattr(src, k, None), models.Model) }
    src_dict.update(fks)
    return src_dict

答案 4 :(得分:-1)

因此,如果我正确解释您的问题,您有一个旧模型(Profile),并且您尝试将其替换为新模型SurveyProfile。鉴于这种情况,您可能需要考虑长期使用South之类的数据库迁移工具。现在,您可以在Django shell(manage.py shell)中运行脚本:

from yourappname.models import *
for profile in Profile.objects.all():
    survey_profile = SurveyProfile()
    # Assuming SurveyUser has user = ForeignKey(User)...
    survey_profile.user = SurveyUser.objects.get(user=profile.user)
    survey_profile.car = profile.car
    survey_profile.job = profile.job
    survey_profile.save()

使用South

如果需要长期维护和更新此项目,我强烈建议使用像South这样的数据库迁移包,它可以让您修改模型上的字段,并轻松地迁移您的数据库。 / p>

例如,您建议您的原始模型存在太多ManyToManyField。南方,你:

  1. 删除模型中的字段。
  2. 自动生成架构迁移。
  3. 应用迁移。
  4. 这使您可以重用所有旧代码,而无需更改模型名称或使用数据库。