ปัญหาเกี่ยวกับประเภทเนื้อหาเมื่อโหลดฟิกซ์เจอร์ใน Django


105

ฉันมีปัญหาในการโหลดโปรแกรม Django ลงในฐานข้อมูล MySQL เนื่องจากความขัดแย้งของประเภทเนื้อหา ก่อนอื่นฉันลองทิ้งข้อมูลจากแอปของฉันเท่านั้นดังนี้:

./manage.py dumpdata escola > fixture.json

แต่ฉันยังคงได้รับปัญหาคีย์ต่างประเทศหายไปเนื่องจากแอป "escola" ของฉันใช้ตารางจากแอปพลิเคชันอื่น ฉันยังคงเพิ่มแอปพลิเคชันเพิ่มเติมจนกว่าจะถึงสิ่งนี้:

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

ตอนนี้ปัญหาคือการละเมิดข้อ จำกัด ต่อไปนี้เมื่อฉันพยายามโหลดข้อมูลเป็นอุปกรณ์ทดสอบ:

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

ดูเหมือนว่าปัญหาคือ Django กำลังพยายามสร้างประเภทเนื้อหาแบบไดนามิกโดยมีค่าคีย์หลักที่แตกต่างกันซึ่งขัดแย้งกับค่าคีย์หลักจากฟิกซ์เจอร์ สิ่งนี้ดูเหมือนจะเหมือนกับข้อบกพร่องที่บันทึกไว้ที่นี่: http://code.djangoproject.com/ticket/7052

ปัญหาคือวิธีแก้ปัญหาที่แนะนำคือทิ้งแอปประเภทเนื้อหาที่ฉันทำอยู่แล้ว!? สิ่งที่ช่วยให้? หากสร้างความแตกต่างฉันมีสิทธิ์แบบจำลองที่กำหนดเองตามที่ระบุไว้ที่นี่: http://docs.djangoproject.com/en/dev/ref/models/options/#permissions

คำตอบ:


150

manage.py dumpdata --naturalจะใช้การแสดงคีย์ต่างประเทศที่ทนทานกว่า ใน django พวกเขาเรียกว่า "คีย์ธรรมชาติ" ตัวอย่างเช่น:

  • Permission.codename ถูกใช้เพื่อประโยชน์ของ Permission.id
  • User.username ถูกใช้เพื่อประโยชน์ของ User.id

อ่านเพิ่มเติม: ส่วนคีย์ธรรมชาติใน "การทำให้เป็นอนุกรมวัตถุ django"

ข้อโต้แย้งที่เป็นประโยชน์อื่น ๆ สำหรับdumpdata:

  • --indent=4 ทำให้มนุษย์สามารถอ่านได้
  • -e sessions ไม่รวมข้อมูลเซสชัน
  • -e admin ไม่รวมประวัติการดำเนินการของผู้ดูแลระบบในไซต์ผู้ดูแลระบบ
  • -e contenttypes -e auth.Permissionsyncdbยกเว้นวัตถุที่ถูกสร้างขึ้นโดยอัตโนมัติจากคีมาทุกช่วงเวลา ใช้ร่วมกับเท่านั้น--naturalมิฉะนั้นคุณอาจลงเอยด้วยหมายเลขประจำตัวที่ไม่เหมาะสม

1
@skyjur ทำไมต้องใช้-e contenttypes -e auth.permissionด้วย--natural? ฉันเพิ่งลองโดยไม่มี--naturalตัวเลือกและมันได้ผล นอกจากนี้เอกสารที่นี่ยังระบุว่าควรใช้ตัวเลือกนี้หากDUMPING auth.permissionและcontenttypes.
wln Nirvana

6
@win Nirvana เพราะหลังจากที่คุณเริ่มต้นจากศูนย์และทำ syncdb สร้างขึ้นใหม่ContentTypeและPermissionไม่รับประกันว่าจะได้รับ id เหมือนที่เคยมีมา การถ่ายโอนข้อมูลของคุณมีรหัสซึ่งอาจอ้างอิงถึงวัตถุต่าง ๆ บนฐานข้อมูล anather ที่คุณจะโหลดข้อมูล อาจได้ผลสำหรับคุณเนื่องจากสาเหตุเหล่านี้ 1) ข้อมูลของคุณไม่มีการอ้างอิงถึงออบเจ็กต์เหล่านี้ 2) รหัสเดิมของ Permission / ContentTypes ถูกเก็บรักษาไว้ 3) loaddata ของคุณประสบความสำเร็จ แต่คุณมีข้อมูลที่เสียหายเนื่องจากออบเจ็กต์ อ้างถึงวัตถุที่ไม่ถูกต้องและคุณยังไม่รู้เกี่ยวกับเรื่องนี้
สกี

12
--naturalขณะนี้การตั้งค่าสถานะถูกยกเลิกเพื่อสนับสนุน--natural-foreign(และ--natural-primary)
ตั้งแต่

16
คำสั่งสุดท้ายอาจเป็น:manage.py dumpdata --natural-foreign --natural-primary -e contenttypes -e auth.Permission --indent 4 > project_dump.json
Paolo

4
--naturalตอนนี้ได้ถูกลบออกไปแล้วไม่ใช่แค่เลิกใช้งาน ใช้--natural-foreignหรือ--natural-primaryแทน
Code-Apprentice

35

ใช่นี่เป็นเรื่องที่น่ารำคาญจริงๆ ในขณะที่ฉันแก้ไขโดยทำการ "Manage.py reset" บนแอปประเภทเนื้อหาก่อนที่จะโหลดฟิกซ์เจอร์ (เพื่อกำจัดข้อมูลประเภทเนื้อหาที่สร้างขึ้นโดยอัตโนมัติซึ่งแตกต่างจากเวอร์ชันที่ถูกทิ้ง) มันใช้งานได้ แต่ในที่สุดฉันก็เบื่อหน่ายกับความยุ่งยากและละทิ้งการติดตั้งทั้งหมดเพื่อสนับสนุนการทิ้ง SQL แบบตรง (แน่นอนว่าคุณจะสูญเสียความสามารถในการพกพา DB)

ปรับปรุง - คำตอบที่ดีที่สุดคือใช้--naturalแฟล็กเพื่อdumpdataตามที่ระบุไว้ในคำตอบด้านล่าง ยังไม่มีการตั้งค่าสถานะนั้นเมื่อฉันเขียนคำตอบนี้


3
ฉันก็เจอเรื่องนี้เช่นกันการรีเซ็ตแอปประเภทเนื้อหาก็ใช้ได้เช่นกัน ขอบคุณสำหรับทิป!
Beau

คุณรีเซ็ตได้อย่างไร ในชั้นกรณีทดสอบ? โปรดยกตัวอย่างให้ฉัน
Oleg Tarasenko

4
ฉันไม่ใช้การแข่งขันสำหรับ unittests โดยทั่วไปฉันจะสร้างข้อมูลการทดสอบโดยใช้ ORM ในวิธีการตั้งค่า () เพราะง่ายต่อการซิงค์กับการทดสอบ ดังนั้นฉันจึงไม่ต้องทำสิ่งนี้ในคลาส TestCase แม้ว่าฉันจะแน่ใจว่าคุณโผล่เข้ามาในโค้ดสำหรับคลาส TestCase ของ Django คุณสามารถหาวิธีทำให้การรีเซ็ตเกิดขึ้นโพสต์ syncdb และก่อนที่จะติดตั้งการโหลดในคลาสย่อย สำหรับฉันมันเป็นแค่ "./manage.py reset contenttypes" ใน bash script ก่อน "./manage.py loaddata my_fixture"
Carl Meyer

32

ลองข้ามประเภทเนื้อหาเมื่อสร้างฟิกซ์เจอร์:

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

มันได้ผลสำหรับฉันในสถานการณ์ที่คล้ายกันสำหรับการทดสอบหน่วยความเข้าใจของคุณเกี่ยวกับประเภทเนื้อหาช่วยได้จริงๆ!



11

ฉันไม่ได้ใช้ MySQL แต่นำเข้าข้อมูลบางส่วนจากเซิร์ฟเวอร์จริงไปยัง sqlite แทน การล้างcontenttypesข้อมูลแอปก่อนดำเนินการloaddataมีเคล็ดลับ:

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

แล้ว

python manage.py loaddata data.json

django.core.exceptions.ImproperlyConfigured: การตั้งค่าที่ร้องขอ INSTALLED_APPS แต่ไม่ได้กำหนดค่าการตั้งค่า คุณต้องกำหนดตัวแปรสภาพแวดล้อม DJANGO_SETTINGS_MODULE หรือเรียก settings.configure () ก่อนเข้าถึงการตั้งค่า
Barney

มันน่าจะทำงานได้ดีที่สุดภายในแฮนเดิลของคำสั่งจัดการแบบกำหนดเอง
Barney

10

ฉันได้แก้ไขปัญหานี้ในกรณีทดสอบของฉันโดยการรีเซ็ตแอปประเภทเนื้อหาจากการทดสอบหน่วยก่อนที่จะโหลดไฟล์ดัมพ์ของฉัน Carl แนะนำสิ่งนี้แล้วโดยใช้manage.pyคำสั่งและฉันทำสิ่งเดียวกันโดยใช้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)

full_test_data.jsonฟิกซ์เจอร์ของฉันมีดัมพ์แอพประเภทเนื้อหาที่สอดคล้องกับข้อมูลทดสอบที่เหลือ IntegrityErrorโดยการตั้งค่าแอปก่อนที่จะโหลดจะป้องกันไม่ให้คีย์ที่ซ้ำกัน


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

สิ่งนี้ใช้ได้กับฉัน ที่นี่ฉันไม่รวมทุกสิ่งที่เป็นฟองรุ่นจริง

  • หากคุณเห็นโมเดลอื่นนอกเหนือจากโมเดลที่คุณสร้างขึ้นคุณสามารถยกเว้นโมเดลเหล่านั้นได้อย่างปลอดภัย ข้อเสียเปรียบประการหนึ่งของวิธีนี้คือคุณไม่ใส่ใจกับข้อมูลบันทึกและข้อมูลการตรวจสอบสิทธิ์

6

คุณต้องใช้คีย์ธรรมชาติเพื่อแสดงคีย์ต่างประเทศและความสัมพันธ์แบบกลุ่มต่อกลุ่ม นอกจากนี้อาจเป็นความคิดที่ดีที่จะยกเว้นsessionตารางในsessionsแอพและlogentryตารางในไฟล์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

อ้างอิงถึงเอกสาร Django , --naturalได้รับการคัดค้านในรุ่น 1.7 เพื่อให้ตัวเลือก--natural-foreignควรจะนำมาใช้แทน

คุณยังสามารถละเว้นคีย์หลักในข้อมูลที่ทำให้เป็นอนุกรมของออบเจ็กต์นี้ได้เนื่องจากสามารถคำนวณได้ในระหว่างการดีซีเรียล--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

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

จะเปลี่ยน

  "content_type": 123

ถึง

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

และการติดตั้งใช้งานได้ในTestCaseขณะนี้


2

Django 2.2.5

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

มันช่วยฉัน


จะทำให้เกิดปัญหาเมื่อ loaddata อาจไม่ตรงกับประเภทเนื้อหาในฐานข้อมูลใหม่
Yang zhou

1

ฉันจะให้คำตอบที่เป็นไปได้อื่นที่ฉันเพิ่งรู้ บางทีมันอาจจะช่วย OP ได้บางทีมันอาจจะช่วยคนอื่นได้

ฉันมีตารางความสัมพันธ์แบบกลุ่มต่อกลุ่ม มีคีย์หลักและคีย์ต่างประเทศสองตัวสำหรับตารางอื่น ๆ ฉันพบว่าถ้าฉันมีรายการในฟิกซ์เจอร์ซึ่งมีคีย์ต่างประเทศสองอันเหมือนกับรายการอื่นที่มีอยู่แล้วในตารางที่มีรายการอื่น PK ก็จะล้มเหลว ตารางความสัมพันธ์ M2M มี "เฉพาะร่วมกัน" สำหรับคีย์ต่างประเทศทั้งสอง

ดังนั้นหากเป็นความสัมพันธ์ M2M ที่กำลังแตกให้ดูคีย์ต่างประเทศที่เพิ่มเข้าไปดูที่ฐานข้อมูลของคุณเพื่อดูว่า FK คู่นั้นอยู่ในรายการภายใต้ PK ที่แตกต่างกันหรือไม่


1

มันช่างน่ารำคาญจริงๆ .. ฉันโดนมันกัดทุกครั้ง

ฉันพยายามทิ้งข้อมูลด้วย - ยกเว้นประเภทเนื้อหาและ - ธรรมชาติฉันมักจะพบปัญหา ..

สิ่งที่ดีที่สุดสำหรับฉันคือทำtruncate table django_content_type;หลังจาก syncdb แล้วโหลดข้อมูล

แน่นอนสำหรับ initial_data.json การโหลดอัตโนมัติคุณกำลังล้มเหลว


สำหรับฉันการตัดตารางก่อนโหลดข้อมูลทำให้เกิดข้อผิดพลาดที่แตกต่างกัน ไม่มีโชคกับเทคนิคนี้
shacker

1

บางครั้งฉันเคยพบข้อผิดพลาดที่คล้ายกัน ปรากฎว่าฉันพยายามโหลดส่วนควบก่อนที่จะสร้างตารางที่จำเป็น ดังนั้นฉันจึง:

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

และมันทำงานได้อย่างมีเสน่ห์


0

ในกรณีของฉันฉันได้ทิ้งข้อมูลจากauth( ./manage.py dumpddata auth > fixtures/auth.json) เพื่อใช้ฟิกซ์เจอร์เพื่อการทดสอบ

การพัฒนาดำเนินต่อไปและฉันได้ลบโมเดลส่วนใหญ่ที่ฉันกำหนดไว้models.pyและนี่คือตอนที่ฉันเริ่มเห็นปัญหาที่น่ารำคาญนี้

วิธีแก้ปัญหาของฉันกำลังสร้างฟิกซ์เจอร์ auth.json อีกครั้ง อันนี้ได้ลบรายการauth.permissionที่เกี่ยวข้องกับรุ่นเก่าที่ฉันมีออกไปมากมาย


0

ฉันลองทุกวิธีจากด้านบนไม่มีอะไรได้ผลสำหรับฉัน ฉันต้องยกเว้นรูปแบบการตรวจสอบสิทธิ์ทั้งหมดและใช้งานได้ดี

python manage.py dumpdata --natural-primary --exclude=contenttypes --exclude=auth --exclude=admin.logentry --exclude=sessions.session --indent 4 > live.json
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.