web-dev-qa-db-fra.com

Problèmes avec les types de contenu lors du chargement d'un appareil dans Django

Je ne parviens pas à charger les appareils Django dans ma base de données MySQL en raison de conflits de types de contenu. J'ai d'abord essayé de vider les données de mon application comme ceci:

./manage.py dumpdata escola > fixture.json

mais des problèmes de clé étrangère me manquaient, car mon application "escola" utilise des tableaux d'autres applications. J'ai continué à ajouter des applications supplémentaires jusqu'à arriver à ceci:

./manage.py dumpdata contenttypes auth escola > fixture.json

Maintenant, le problème est la violation de contrainte suivante lorsque j'essaie de charger les données en tant que dispositif de test:

IntegrityError: (1062, "Duplicate entry 'escola-t23aluno' for key 2")

Il semble que le problème est que Django tente de recréer de manière dynamique des types de contenu avec différentes valeurs de clé primaire en conflit avec les valeurs de clé primaire du projecteur. Cela semble être le même que le bogue documenté ici: http://code.djangoproject.com/ticket/7052

Le problème est que la solution de contournement recommandée consiste à vider l'application contenttypes que je fais déjà!? Ce qui donne? Si cela fait une différence, j'ai des autorisations de modèle personnalisées décrites ici: http://docs.djangoproject.com/en/dev/ref/models/options/#permissions

97
user27478

manage.py dumpdata --natural utilisera une représentation plus durable des clés étrangères. À Django, on les appelle "clés naturelles". Par exemple:

  • Permission.codename est utilisé en faveur de Permission.id
  • User.username est utilisé en faveur de User.id

En savoir plus: Section des clés naturelles dans "Sérialisation des objets Django"

Quelques autres arguments utiles pour dumpdata:

  • --indent=4 le rendre lisible par l'homme.
  • -e sessions exclure les données de session
  • -e admin exclure l'historique des actions de l'administrateur sur le site de l'administrateur
  • -e contenttypes -e auth.Permission exclut les objets qui sont recréés automatiquement du schéma à chaque fois pendant syncdb. Utilisez-le uniquement avec --natural, sinon vous pourriez vous retrouver avec des identifiants mal alignés.
131
Ski

Oui, c'est vraiment irritant. Pendant un certain temps, j'ai travaillé dessus en effectuant une "réinitialisation manage.py" sur l'application contenttypes avant de charger le projecteur (pour supprimer les données de type de contenu générées automatiquement qui différaient de la version exportée). Cela a fonctionné, mais finalement, j'en ai eu marre des tracas et des appareils abandonnés en faveur des dumps SQL droits (bien sûr, vous perdrez alors la portabilité de la base de données).

update - la meilleure réponse consiste à utiliser l'indicateur --natural en dumpdata, comme indiqué dans une réponse ci-dessous. Ce drapeau n'existait pas encore lorsque j'ai écrit cette réponse.

33
Carl Meyer

Essayez de sauter les types de contenu lors de la création d'un appareil:

./manage.py dumpdata --exclude contenttypes > fixture.json

Cela a fonctionné pour moi dans une situation similaire pour les tests unitaires, votre compréhension des types de contenu a vraiment aidé!

30
Evgeny

Les réponses ici toutes anciennes ... À partir de 2017, la meilleure réponse est:

manage.py dumpdata --natural-foreign --natural-primary -e contenttypes -e auth.Permission --indent 4
24
SmallChess

J'ai résolu ce problème dans mes cas de test en réinitialisant l'application contenttypes à partir du test unitaire avant de charger mon fichier de vidage. Carl a déjà suggéré cela en utilisant la commande manage.py et je fais la même chose en utilisant la méthode call_command:

>>> from Django.core import management
>>> management.call_command("flush", verbosity=0, interactive=False)
>>> management.call_command("reset", "contenttypes", verbosity=0, interactive=False)
>>> management.call_command("loaddata", "full_test_data.json", verbosity=0)

Mon appareil full_test_data.json contient le dump de l'application contenttypes qui correspond au reste des données de test. En réinitialisant l'application avant le chargement, cela évite la duplication de la clé IntegrityError.

10
Jesse L

Je n'utilisais pas MySQL, mais importais plutôt des données d'un serveur live dans sqlite. Effacer les données de l'application contenttypes avant d'exécuter loaddata a été efficace:

from Django.contrib.contenttypes.models import ContentType
ContentType.objects.all().delete()
quit()

Et alors

python manage.py loaddata data.json
9
MadeOfAir
python manage.py dumpdata --natural-primary --exclude=contenttypes --exclude=auth.Permission --exclude=admin.logentry --exclude=sessions.session --indent 4 > initial_data.json

Cela fonctionne pour moi. Ici, tout est exclu des modèles actuels. 

  • Si vous voyez un autre modèle que ceux que vous avez créés, vous pouvez les exclure en toute sécurité. Un inconvénient de cette approche est que vous perdez des données de journal ainsi que des données d'authentification. 
6
Ojas Kale

Je vais donner une autre réponse possible que je viens de comprendre. Peut-être que ça va aider le PO, peut-être que ça va aider quelqu'un d'autre.

J'ai une table de relation plusieurs à plusieurs. Il a une clé primaire et les deux clés étrangères des autres tables. J'ai constaté que si j'ai une entrée dans le dispositif dont les deux clés étrangères sont identiques à une autre entrée déjà dans la table avec un différent pk, cela échouera. Les tables de relations M2M ont un "ensemble unique" pour les deux clés étrangères.

Ainsi, si une relation M2M est en train de se rompre, examinez les clés étrangères qu’elle ajoute, examinez votre base de données pour voir si cette paire de FK figure déjà sous un autre PK.

1
orblivion
./manage.py dumpdata app.Model --natural-foreign

changera 

  "content_type": 123

à

  "content_type": [
    "app_label",
    "model"
  ],

Et le montage fonctionne pour TestCase maintenant

1
Daniil Mashkin

J'avais rencontré une erreur similaire parfois auparavant. Il s'est avéré que j'essayais de charger les fixtures avant de créer les tables nécessaires. Alors j'ai fait:

$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py loaddata fixtures/initial_data.json

Et ça a fonctionné comme un charme

1
James Wanderi

C'est vraiment, vraiment énervant… Je me fais piquer à chaque fois.

J'ai essayé de dumpdata avec --exclude contenttypes et --natural, j'ai toujours des problèmes ..

Ce qui me convient le mieux est simplement de faire un truncate table Django_content_type; après la synchronisation et de charger les données.

Bien sûr, pour initial_data.json, le chargement automatique est une erreur.

1
h3.

Vous devez utiliser des clés naturelles pour représenter toute clé étrangère et toute relation plusieurs à plusieurs. De plus, il peut être judicieux d'exclure la table session de l'application sessions et la table logentry de l'application admin.

Django 1.7+

python manage.py dumpdata --natural-foreign --exclude contenttypes --exclude auth.permission --exclude admin.logentry --exclude sessions.session --indent 4 > fixture.json

Django <1.7

python manage.py dumpdata --natural --exclude contenttypes --exclude auth.permission --exclude admin.logentry --exclude sessions.session --indent 4 > fixture.json

D'après la documentation Django , --natural est obsolète dans la version 1.7, l'option --natural-foreign doit donc être utilisée à la place.

Vous pouvez également omettre la clé primaire dans les données sérialisées de cet objet, car elle peut être calculée pendant la désérialisation en passant l'indicateur --natural-primary.

python manage.py dumpdata --natural-foreign --natural-primary --exclude contenttypes --exclude auth.permission --exclude admin.logentry --exclude sessions.session --indent 4 > fixture.json
0
lmiguelvargasf