6

我必须建模。我想将模型对象从一个模型复制到另一个模型:模型 2 是模型 1 的副本(这个模型有太多 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)

如何将用户配置文件从 Profile 复制到 SurveyProfile。

提前致谢

4

5 回答 5

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类并将其继承为Profileand的具体类SurveyProfile,但这不会影响我上面所说的)

于 2012-05-30T15:02:18.387 回答
3

我很难理解你上面写的内容,因此我不能 100% 确定这是否可行,但如果我理解你的话,我想我会做的是这样的事情:

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

接着

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

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

于 2012-05-30T13:54:45.630 回答
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)
于 2013-10-07T13:08:14.057 回答
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
于 2018-05-23T15:36:19.670 回答
-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这样的数据库迁移包,它可以让您修改模型上的字段,并轻松迁移数据库。

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

  1. 从模型中删除字段。
  2. 自动生成架构迁移。
  3. 应用迁移。

这使您可以重用所有旧代码,而无需更改模型名称或与数据库混淆。

于 2012-05-31T04:48:12.390 回答