Foo.objects.get(pk="foo")
<Foo: test>
Dans la base de données, je veux ajouter un autre objet qui est une copie de l'objet ci-dessus.
Supposons que ma table ait une ligne. Je veux insérer le premier objet de ligne dans une autre ligne avec une clé primaire différente. Comment puis je faire ça?
python
django
django-models
user426795
la source
la source
obj.pk
etobj.id
faire ce travail dans Django 1.4La documentation Django pour les requêtes de base de données comprend une section sur la copie des instances de modèle . En supposant que vos clés primaires sont générées automatiquement, vous obtenez l'objet que vous souhaitez copier, définissez la clé primaire
None
et enregistrez à nouveau l'objet:Dans cet extrait, le premier
save()
crée l'objet d'origine et le secondsave()
crée la copie.Si vous continuez à lire la documentation, il existe également des exemples sur la façon de gérer deux cas plus complexes: (1) copie d'un objet qui est une instance d'une sous-classe de modèle, et (2) copie également des objets connexes, y compris des objets dans plusieurs-à -de nombreuses relations.
Remarque sur la réponse de miah: régler le pk sur
None
est mentionné dans la réponse de miah, bien qu'il ne soit pas présenté à l'avant et au centre. Donc ma réponse sert principalement à souligner cette méthode comme étant la manière recommandée par Django de le faire.Note historique: Cela n'a pas été expliqué dans les documents Django jusqu'à la version 1.4. Cela a été possible depuis avant 1.4 cependant.
Fonctionnalité future possible: la modification des documents susmentionnée a été effectuée dans ce ticket . Sur le fil de commentaires du ticket, il y avait aussi une discussion sur l'ajout d'une
copy
fonction intégrée pour les classes de modèles, mais pour autant que je sache, ils ont décidé de ne pas s'attaquer à ce problème pour le moment. Cette méthode de copie "manuelle" devra donc probablement le faire pour l'instant.la source
Faites attention ici. Cela peut être extrêmement coûteux si vous êtes dans une boucle quelconque et que vous récupérez les objets un par un. Si vous ne voulez pas l'appel à la base de données, faites simplement:
Il fait la même chose que certaines de ces autres réponses, mais il n'appelle pas la base de données pour récupérer un objet. Ceci est également utile si vous souhaitez faire une copie d'un objet qui n'existe pas encore dans la base de données.
la source
Utilisez le code ci-dessous:
la source
model_to_dict
prend unexclude
paramètre, ce qui signifie que vous n'avez pas besoin de séparerpop
:model_to_dict(instance, exclude=['id'])
Il y a un extrait de clone ici , que vous pouvez ajouter à votre modèle:
la source
if
doit maintenant êtreif fld.name != old._meta.pk.name
, c'est-à-dire laname
propriété de l'_meta.pk
instance.Comment faire cela a été ajouté aux documents officiels de Django dans Django1.4
https://docs.djangoproject.com/en/1.10/topics/db/queries/#copying-model-instances
La réponse officielle est similaire à la réponse de miah, mais les documents soulignent certaines difficultés avec l'héritage et les objets associés, vous devez donc probablement vous assurer de lire les documents.
la source
stable
place du numéro de version dans l'URL, comme ceci: docs.djangoproject.com/en/stable/topics/db/queries/…J'ai rencontré quelques accrochages avec la réponse acceptée. Voici ma solution.
Remarque: cela utilise des solutions qui ne sont pas officiellement approuvées dans les documents Django, et elles pourraient cesser de fonctionner dans les futures versions. J'ai testé cela en 1.9.13.
La première amélioration est qu'elle vous permet de continuer à utiliser l'instance d'origine, en utilisant
copy.copy
. Même si vous n'avez pas l'intention de réutiliser l'instance, il peut être plus sûr de faire cette étape si l'instance que vous clonez a été passée comme argument à une fonction. Sinon, l'appelant aura de manière inattendue une instance différente lorsque la fonction reviendra.copy.copy
semble produire une copie superficielle d'une instance de modèle Django de la manière souhaitée. C'est l'une des choses que je n'ai pas trouvées documentées, mais cela fonctionne en décapant et en décollant, donc c'est probablement bien pris en charge.Deuxièmement, la réponse approuvée laissera tous les résultats prélus attachés à la nouvelle instance. Ces résultats ne doivent pas être associés à la nouvelle instance, sauf si vous copiez explicitement les relations to-many. Si vous parcourez les relations prélues, vous obtiendrez des résultats qui ne correspondent pas à la base de données. La rupture du code de travail lorsque vous ajoutez une prélecture peut être une mauvaise surprise.
La suppression
_prefetched_objects_cache
est un moyen rapide et sale de supprimer tous les préfixes. Les accès ultérieurs à plusieurs fonctionnent comme s'il n'y avait jamais eu de prélecture. L'utilisation d'une propriété non documentée qui commence par un trait de soulignement pose probablement des problèmes de compatibilité, mais cela fonctionne pour l'instant.la source
_[model_name]_cache
, qui, une fois supprimée, j'ai pu attribuer un nouvel ID pour ce modèle associé, puis appelersave()
. Il pourrait encore y avoir des effets secondaires que je n'ai pas encore déterminés.mettre pk sur None est meilleur, Sinse Django peut créer correctement un pk pour vous
la source
C'est encore une autre façon de cloner l'instance de modèle:
la source
Pour cloner un modèle avec plusieurs niveaux d'héritage, c'est-à-dire> = 2, ou ModelC ci-dessous
Veuillez renvoyer la question ici .
la source
Essaye ça
la source