Duplicate Django Model Instance and All Foreign Keys Pointing to It

后端 未结 4 461
自闭症患者
自闭症患者 2021-01-02 06:03

I want to create a method on a Django model, call it model.duplicate(), that duplicates the model instance, including all the foreign keys pointing to it. I kno

4条回答
  •  长发绾君心
    2021-01-02 06:15

    You can create new instance and save it like this

    def duplicate(self):
        kwargs = {}
        for field in self._meta.fields:
            kwargs[field.name] = getattr(self, field.name)
            # or self.__dict__[field.name]
        kwargs.pop('id')
        new_instance = self.__class__(**kwargs)
        new_instance.save()
        # now you have id for the new instance so you can
        # create related models in similar fashion
        fkeys_qs = self.fkeys.all()
        new_fkeys = []
        for fkey in fkey_qs:
            fkey_kwargs = {}
            for field in fkey._meta.fields:
                fkey_kwargs[field.name] = getattr(fkey, field.name)
            fkey_kwargs.pop('id')
            fkey_kwargs['foreign_key_field'] = new_instance.id
            new_fkeys.append(fkey_qs.model(**fkey_kwargs))
        fkeys_qs.model.objects.bulk_create(new_fkeys)
        return new_instance
    

    I'm not sure how it'll behave with ManyToMany fields. But for simple fields it works. And you can always pop the fields you are not interested in for your new instance.

    The bits where I'm iterating over _meta.fields may be done with copy but the important thing is to use the new id for the foreign_key_field.

    I'm sure it's programmatically possible to detect which fields are foreign keys to the self.__class__ (foreign_key_field) but since you can have more of them it'll better to name the one (or more) explicitly.

提交回复
热议问题