Masalah dengan jenis konten saat memuat perlengkapan di Django

104

Saya mengalami masalah saat memuat perlengkapan Django ke database MySQL saya karena konflik tipe konten. Pertama saya mencoba membuang data hanya dari aplikasi saya seperti ini:

./manage.py dumpdata escola > fixture.json

tetapi saya terus mendapatkan masalah kunci asing yang hilang, karena aplikasi saya "escola" menggunakan tabel dari aplikasi lain. Saya terus menambahkan aplikasi tambahan sampai saya mendapatkan ini:

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

Sekarang masalahnya adalah pelanggaran batasan berikut ketika saya mencoba memuat data sebagai perlengkapan uji:

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

Tampaknya masalahnya adalah Django sedang mencoba membuat ulang tipe konten secara dinamis dengan nilai kunci utama berbeda yang bertentangan dengan nilai kunci utama dari perlengkapan. Tampaknya ini sama dengan bug yang didokumentasikan di sini: http://code.djangoproject.com/ticket/7052

Masalahnya adalah solusi yang disarankan adalah membuang aplikasi contenttypes yang sudah saya lakukan !? Apa yang memberi? Jika ada bedanya, saya memiliki beberapa izin model khusus seperti yang didokumentasikan di sini: http://docs.djangoproject.com/en/dev/ref/models/options/#permissions

gerdemb
sumber

Jawaban:

148

manage.py dumpdata --naturalakan menggunakan representasi kunci asing yang lebih tahan lama. Dalam django mereka disebut "kunci alami". Sebagai contoh:

  • Permission.codename digunakan untuk mendukung Permission.id
  • User.username digunakan untuk mendukung User.id

Baca lebih lanjut: bagian kunci alami dalam "membuat serial objek django"

Beberapa argumen berguna lainnya untuk dumpdata:

  • --indent=4 membuatnya bisa dibaca manusia.
  • -e sessions kecualikan data sesi
  • -e admin kecualikan riwayat tindakan admin di situs admin
  • -e contenttypes -e auth.Permissionkecualikan objek yang dibuat ulang secara otomatis dari skema setiap kali selama syncdb. Gunakan hanya dengan --naturalatau Anda mungkin akan berakhir dengan nomor id yang tidak sesuai.
Main ski
sumber
1
@skyjur Mengapa selalu digunakan -e contenttypes -e auth.permissiondengan --natural? Saya hanya mencoba tanpa --naturalopsi dan berhasil. Juga dokumentasi di sini mengatakan seseorang harus menggunakan opsi ini jika DUMPING auth.permission dan contenttypes.
wlnirvana
6
@winirvana karena setelah Anda mulai dari awal dan melakukan syncdb, baru dibuat ContentTypedan Permissiontidak dijamin mendapatkan id yang sama seperti sebelumnya. Dump data Anda berisi id yang mungkin mereferensikan objek berbeda pada database lain tempat Anda akan memuat data. Ini mungkin berhasil untuk Anda karena salah satu alasan berikut: 1) data Anda tidak memiliki referensi ke objek ini 2) ID asli dari Permission / ContentTypes dipertahankan 3) loaddata Anda berhasil tetapi Anda sebenarnya memiliki data yang rusak karena objek mengacu pada objek yang salah dan Anda belum mengetahuinya
Ski
12
Bendera --naturalsekarang sudah tidak digunakan lagi demi --natural-foreign(dan --natural-primary)
frnhr
16
Perintah terakhir bisa jadi:manage.py dumpdata --natural-foreign --natural-primary -e contenttypes -e auth.Permission --indent 4 > project_dump.json
Paolo
4
--naturalsekarang telah dihapus sepenuhnya, tidak hanya usang. Gunakan --natural-foreignatau --natural-primarysebagai gantinya.
Code-Apprentice
35

Ya, ini sangat menjengkelkan. Untuk sementara saya mengatasinya dengan melakukan "manage.py reset" pada aplikasi contenttypes sebelum memuat fixture (untuk menyingkirkan data contenttypes yang dibuat secara otomatis yang berbeda dari versi yang dibuang). Itu berhasil, tetapi akhirnya saya muak dengan kerepotan dan perlengkapan yang ditinggalkan sepenuhnya demi SQL langsung (tentu saja, Anda kehilangan portabilitas DB).

update - jawaban terbaik adalah menggunakan --naturalflag to dumpdata, seperti yang tercantum dalam jawaban di bawah. Bendera itu belum ada saat saya menulis jawaban ini.

Carl Meyer
sumber
3
Saya mengalami ini juga, mengatur ulang aplikasi tipe konten juga berfungsi untuk saya. Terima kasih atas tipnya!
Beau
Bagaimana Anda meresetnya? Di kelas kasus uji? Tolong beri saya contoh
Oleg Tarasenko
4
Saya tidak menggunakan perlengkapan untuk unittests, saya biasanya membuat data pengujian menggunakan ORM dalam metode setup () karena lebih mudah untuk tetap sinkron dengan pengujian. Jadi saya tidak pernah harus melakukan ini di kelas TestCase, meskipun saya yakin jika Anda melihat-lihat kode untuk kelas TestCase Django Anda bisa mengetahui bagaimana membuat reset terjadi post syncdb dan sebelum fixture memuat dalam subkelas. Bagi saya itu hanya "./manage.py reset contenttypes" dalam skrip bash sebelum "./manage.py loaddata my_fixture".
Carl Meyer
32

Coba lewati jenis konten saat membuat perlengkapan:

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

Ini berfungsi untuk saya dalam situasi yang sama untuk pengujian unit, wawasan Anda tentang jenis konten sangat membantu!

Evgeny
sumber
31

Jawabannya di sini semua tua ... Pada 2017, jawaban terbaik adalah:

manage.py dumpdata --natural-foreign --natural-primary -e contenttypes -e auth.Permission --indent 4
Halo Dunia
sumber
11

Saya tidak menggunakan MySQL tetapi mengimpor beberapa data dari server langsung ke sqlite. Menghapus contenttypesdata aplikasi sebelum melakukan loaddatatriknya:

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

Lalu

python manage.py loaddata data.json
MadeOfAir
sumber
django.core.exceptions.ImproperlyConfigured: Pengaturan yang diminta INSTALLED_APPS, tetapi pengaturan tidak dikonfigurasi. Anda harus menentukan variabel lingkungan DJANGO_SETTINGS_MODULE atau memanggil settings.configure () sebelum mengakses pengaturan.
Barney
Ini mungkin akan bekerja paling baik dalam pegangan perintah manajemen kustom.
Barney
10

Saya telah menyelesaikan masalah ini dalam kasus pengujian saya dengan menyetel ulang aplikasi jenis konten dari pengujian unit sebelum memuat file dump saya. Carl menyarankan ini sudah menggunakan manage.pyperintah dan saya melakukan hal yang sama hanya dengan menggunakan call_commandmetode:

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

full_test_data.jsonPerlengkapan saya berisi dump app contenttypes yang sesuai dengan data pengujian lainnya. Dengan mengatur ulang aplikasi sebelum memuat, ini mencegah kunci duplikat IntegrityError.

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

Ini berhasil untuk saya. Di sini saya tidak memasukkan semuanya ke model yang sebenarnya.

  • Jika Anda melihat model lain selain model yang Anda buat, Anda dapat mengecualikannya dengan aman. Salah satu kelemahan dari pendekatan ini adalah Anda kehilangan data log serta data autentikasi.
Ojas Kale
sumber
6

Anda perlu menggunakan kunci alami untuk mewakili kunci asing dan hubungan banyak ke banyak. Selain itu, mungkin ada baiknya untuk mengecualikan sessiontabel di sessionsaplikasi, dan logentrytabel di adminaplikasi.

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

Menurut dokumentasi Django , --naturalsudah tidak digunakan lagi dalam versi 1.7, jadi opsi --natural-foreignharus digunakan sebagai gantinya.

Anda juga dapat menghilangkan kunci utama dalam data serial dari objek ini karena dapat dihitung selama deserialisasi dengan meneruskan --natural-primarybendera.

python manage.py dumpdata --natural-foreign --natural-primary --exclude contenttypes --exclude auth.permission --exclude admin.logentry --exclude sessions.session --indent 4 > fixture.json
lmiguelvargasf
sumber
2
./manage.py dumpdata app.Model --natural-foreign

akan berubah

  "content_type": 123

untuk

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

Dan perlengkapan berfungsi untuk TestCasesaat ini

Daniil Mashkin
sumber
2

Django 2.2.5

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

itu membantu saya

Igor Z
sumber
Ini akan menimbulkan masalah saat memuat data, mungkin tidak cocok dengan jenis konten di database baru
yang zhou
1

Saya akan memberikan kemungkinan jawaban lain yang baru saja saya temukan. Mungkin itu akan membantu OP, mungkin itu akan membantu orang lain.

Saya punya tabel hubungan banyak-ke-banyak. Ini memiliki kunci utama dan dua kunci asing ke tabel lainnya. Saya menemukan bahwa jika saya memiliki sebuah entri di fixture yang dua kunci asing adalah sama seperti entri lain yang sudah di meja dengan berbeda pk , itu akan gagal. Tabel hubungan M2M memiliki "unik bersama" untuk dua kunci asing.

Jadi, jika itu adalah hubungan M2M yang rusak, lihat kunci asing yang ditambahkannya, lihat database Anda untuk melihat apakah pasangan FK tersebut sudah terdaftar di bawah PK yang berbeda.

orblivion.dll
sumber
1

Benar-benar menjengkelkan .. Aku selalu digigit ini.

Saya mencoba membuang data dengan --exclude contenttypes dan --natural, saya selalu mendapat masalah ..

Apa yang terbaik bagi saya adalah melakukan a truncate table django_content_type; setelah syncdb dan KEMUDIAN memuat data.

Tentu saja untuk pemuatan otomatis initial_data.json Anda gagal.

h3.
sumber
Bagi saya, memotong tabel sebelum loaddata hanya menyebabkan kesalahan yang berbeda. Tidak beruntung dengan teknik ini.
shacker
1

Saya mengalami kesalahan serupa beberapa waktu lalu. Ternyata saya mencoba memuat perlengkapan sebelum membuat tabel yang diperlukan. Jadi saya melakukan:

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

Dan itu bekerja dengan sangat baik

James Wanderi
sumber
0

Dalam kasus saya, saya telah membuang data dari auth( ./manage.py dumpddata auth > fixtures/auth.json) untuk menggunakan fixture untuk tujuan pengujian.

Pengembangan berlanjut dan saya menghapus sebagian besar model yang telah saya definisikan models.py dan inilah saat saya mulai melihat masalah yang mengganggu ini.

Solusi saya adalah meregenerasi fixture auth.json lagi. Yang ini telah menghapus banyak entri yang auth.permissionterkait dengan model lama yang saya miliki.

Pablo Castellano
sumber
0

Saya mencoba setiap metode dari atas, Tidak ada yang berhasil untuk saya. Saya harus mengecualikan model autentikasi lengkap dan berfungsi dengan baik.

python manage.py dumpdata --natural-primary --exclude=contenttypes --exclude=auth --exclude=admin.logentry --exclude=sessions.session --indent 4 > live.json
Chandra Shekhar Pandey
sumber