Problemi con i tipi di contenuto durante il caricamento di un'apparecchiatura in Django


104

Ho problemi a caricare i dispositivi Django nel mio database MySQL a causa di conflitti di tipo di contenuto. Per prima cosa ho provato a scaricare i dati solo dalla mia app in questo modo:

./manage.py dumpdata escola > fixture.json

ma continuavo a riscontrare problemi con le chiavi esterne mancanti, perché la mia app "escola" utilizza tabelle da altre applicazioni. Ho continuato ad aggiungere altre app finché non sono arrivato a questo:

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

Ora il problema è la seguente violazione del vincolo quando provo a caricare i dati come dispositivo di prova:

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

Sembra che il problema sia che Django stia cercando di ricreare dinamicamente tipi di contenuto con diversi valori di chiave primaria che sono in conflitto con i valori di chiave primaria dal dispositivo. Questo sembra essere lo stesso del bug documentato qui: http://code.djangoproject.com/ticket/7052

Il problema è che la soluzione alternativa consigliata è scaricare l'app contenttypes che sto già facendo !? Cosa succede? Se fa qualche differenza, ho alcune autorizzazioni del modello personalizzato come documentato qui: http://docs.djangoproject.com/en/dev/ref/models/options/#permissions

Risposte:


148

manage.py dumpdata --naturalutilizzerà una rappresentazione più durevole delle chiavi esterne. In django sono chiamate "chiavi naturali". Per esempio:

  • Permission.codename è usato a favore di Permission.id
  • User.username è usato a favore di User.id

Per saperne di più: sezione chiavi naturali in "serializzazione di oggetti django"

Alcuni altri argomenti utili per dumpdata:

  • --indent=4 renderlo leggibile dall'uomo.
  • -e sessions escludere i dati della sessione
  • -e admin escludere la cronologia delle azioni dell'amministratore sul sito di amministrazione
  • -e contenttypes -e auth.Permissionescludere gli oggetti che vengono ricreati automaticamente dallo schema ogni volta durante syncdb. Usalo solo insieme, --naturalaltrimenti potresti finire con numeri ID mal allineati.

1
@skyjur Perché usare sempre -e contenttypes -e auth.permissioncon --natural? Ho appena provato senza l' --naturalopzione e ha funzionato. Anche la documentazione qui dice che si dovrebbe usare questa opzione se DUMPING auth.permission e contenttypes.
wlnirvana

6
@winirvana perché dopo aver iniziato da zero e fatto syncdb, appena creato ContentTypee Permissionnon è garantito che ottenga lo stesso ID di prima. Il tuo dump dei dati contiene ID che potrebbero fare riferimento a oggetti diversi su un altro database in cui caricherai i dati. Potrebbe funzionare per te a causa di uno di questi motivi: 1) i tuoi dati non avevano alcun riferimento a questi oggetti 2) gli ID originali di Permission / ContentTypes sono stati conservati 3) i tuoi dati di caricamento hanno avuto successo ma in realtà hai dati corrotti a causa di oggetti riferirsi a oggetti sbagliati e ancora non lo sai
Sci

12
Flag --naturalè ora deprecato a favore di --natural-foreign(e --natural-primary)
venerdì

16
Il comando finale potrebbe essere:manage.py dumpdata --natural-foreign --natural-primary -e contenttypes -e auth.Permission --indent 4 > project_dump.json
Paolo

4
--naturalè stato ora completamente rimosso, non solo deprecato. Usa --natural-foreigno --natural-primaryinvece.
Code-Apprentice

35

Sì, questo è davvero irritante. Per un po 'ci ho aggirato eseguendo un "reset manage.py" sull'app contenttypes prima di caricare il dispositivo (per eliminare i dati di contenttypes generati automaticamente che differivano dalla versione scaricata). Ha funzionato, ma alla fine mi sono stufato dei fastidi e ho abbandonato i dispositivi completamente a favore dei dump SQL diretti (ovviamente, quindi si perde la portabilità del DB).

aggiornamento : la risposta migliore è usare il --naturalflag per dumpdata, come indicato in una risposta di seguito. Quella bandiera non esisteva ancora quando ho scritto questa risposta.


3
Mi stavo imbattendo anche in questo, il ripristino dell'app dei tipi di contenuto ha funzionato anche per me. Grazie per il consiglio!
Beau

Come li hai ripristinati? Nella classe del caso di test? Fammi un esempio per favore
Oleg Tarasenko

4
Non uso fixtures per unittest, generalmente creo dati di test utilizzando l'ORM in un metodo setup () perché è più facile rimanere sincronizzati con i test. Quindi non ho mai dovuto farlo in una classe TestCase, anche se sono sicuro che se dai un'occhiata al codice per la classe TestCase di Django potresti capire come fare un ripristino dopo syncdb e prima del caricamento del dispositivo in una sottoclasse. Per me era solo "./manage.py reset contenttypes" in uno script bash prima di "./manage.py loaddata my_fixture".
Carl Meyer,

32

Prova a saltare i tipi di contenuto durante la creazione del dispositivo:

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

Ha funzionato per me in una situazione simile per i test unitari, la tua intuizione riguardo ai tipi di contenuto ha davvero aiutato!


31

Le risposte qui sono tutte vecchie ... A partire dal 2017, la risposta migliore è:

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

11

Non stavo usando MySQL ma invece importavo alcuni dati da un server live in sqlite. La cancellazione dei contenttypesdati dell'app prima di eseguire loaddataha funzionato:

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

E poi

python manage.py loaddata data.json

django.core.exceptions.ImproperlyConfigured: è stata richiesta l'impostazione INSTALLED_APPS, ma le impostazioni non sono configurate. È necessario definire la variabile d'ambiente DJANGO_SETTINGS_MODULE o chiamare settings.configure () prima di accedere alle impostazioni.
Barney

Probabilmente funzionerebbe meglio all'interno dell'handle di un comando di gestione personalizzato.
Barney

10

Ho risolto questo problema nei miei casi di test reimpostando l'app contenttypes dallo unit test prima di caricare il mio file di dump. Carl lo ha suggerito già usando il manage.pycomando e io faccio la stessa cosa solo usando il call_commandmetodo:

>>> 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)

Il mio full_test_data.jsondispositivo contiene il dump dell'app contenttypes che corrisponde al resto dei dati di test. Reimpostando l'app prima del caricamento, impedisce la duplicazione della chiave IntegrityError.


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

Questo funziona per me. Qui sto escludendo tutto ciò che riguarda i modelli reali.

  • Se vedi qualsiasi altro modello diverso dai modelli che hai creato puoi tranquillamente escluderli. Uno svantaggio di questo approccio è che perdi i dati di registro e quelli di autenticazione.

6

È necessario utilizzare chiavi naturali per rappresentare qualsiasi chiave esterna e relazioni molti-a-molti. Inoltre, potrebbe essere una buona idea escludere la sessiontabella sessionsnell'app e la logentrytabella adminnell'app.

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

Secondo la documentazione di Django , --naturalè stata deprecata nella versione 1.7, quindi l'opzione--natural-foreign dovrebbe essere usata al suo posto.

È inoltre possibile omettere la chiave primaria nei dati serializzati di questo oggetto poiché può essere calcolata durante la deserializzazione passando il --natural-primaryflag.

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

2
./manage.py dumpdata app.Model --natural-foreign

cambierà

  "content_type": 123

per

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

E il dispositivo funziona per TestCaseora


2

Django 2.2.5

python manage.py dumpdata --exclude=contenttypes > datadump.json

mi ha aiutato


Solleverà un problema quando si caricano i dati, forse non corrisponde al tipo di contenuto nel nuovo database
yang zhou

1

Darò un'altra possibile risposta che ho appena scoperto. Forse aiuterà l'OP, forse aiuterà qualcun altro.

Ho una tabella delle relazioni molti-a-molti. Ha una chiave primaria e le due chiavi esterne per le altre tabelle. Ho scoperto che se ho una voce nella fixture le cui due chiavi esterne sono uguali a un'altra voce già in tabella con una diversa pk , fallirà. Le tabelle di relazione M2M hanno un "insieme unico" per le due chiavi esterne.

Quindi, se si tratta di una relazione M2M che si sta interrompendo, guarda le chiavi esterne che sta aggiungendo, guarda il tuo database per vedere se quella coppia di FK è già elencata sotto un PK diverso.


1

È davvero, davvero fastidioso .. Vengo morso da questo ogni singola volta.

Ho provato a eseguire il dump dei dati con --exclude contenttypes e --natural, ho sempre problemi ..

Ciò che funziona meglio per me è semplicemente fare un file truncate table django_content_type; dopo la sincronizzazione e POI caricare i dati.

Ovviamente per il caricamento automatico di initial_data.json sei una fallita.


Per me, il troncamento della tabella prima di loaddata causa solo errori diversi. Nessuna fortuna con questa tecnica.
shacker

1

Avevo riscontrato un errore simile a volte fa. Si è scoperto che stavo cercando di caricare gli infissi prima di creare le tabelle necessarie. Così ho fatto:

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

E ha funzionato a meraviglia


0

Nel mio caso avevo scaricato i dati da auth( ./manage.py dumpddata auth > fixtures/auth.json) per utilizzare il dispositivo a scopo di test.

Lo sviluppo è continuato e ho rimosso la maggior parte dei modelli in cui avevo definito models.py ed è stato allora che ho iniziato a vedere questo fastidioso problema.

La mia soluzione è stata rigenerare nuovamente il dispositivo auth.json. Questo aveva rimosso molte voci inauth.permission relative ai vecchi modelli che avevo.


0

Ho provato tutti i metodi dall'alto, niente ha funzionato per me. Devo escludere il modello di autenticazione completo e funziona bene.

python manage.py dumpdata --natural-primary --exclude=contenttypes --exclude=auth --exclude=admin.logentry --exclude=sessions.session --indent 4 > live.json
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.