Sự cố với các loại nội dung khi tải một vật cố định trong Django


104

Tôi đang gặp sự cố khi tải các đồ đạc Django vào cơ sở dữ liệu MySQL của mình do xung đột kiểu nội dung. Đầu tiên, tôi đã thử kết xuất dữ liệu chỉ từ ứng dụng của mình như thế này:

./manage.py dumpdata escola > fixture.json

nhưng tôi vẫn gặp sự cố thiếu khóa ngoại vì ứng dụng "escola" của tôi sử dụng bảng từ các ứng dụng khác. Tôi tiếp tục thêm các ứng dụng bổ sung cho đến khi tôi nhận được điều này:

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

Bây giờ vấn đề là vi phạm ràng buộc sau khi tôi cố gắng tải dữ liệu dưới dạng một vật cố định thử nghiệm:

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

Có vẻ như vấn đề là Django đang cố gắng tạo lại động các loại nội dung với các giá trị khóa chính khác nhau xung đột với các giá trị khóa chính từ cố định. Điều này có vẻ giống như lỗi được ghi lại ở đây: http://code.djangoproject.com/ticket/7052

Vấn đề là cách giải quyết được đề xuất là hủy ứng dụng contenttypes mà tôi đang làm !? Đưa cái gì? Nếu nó tạo ra bất kỳ sự khác biệt nào, tôi có một số quyền đối với mô hình tùy chỉnh như được ghi lại ở đây: http://docs.djangoproject.com/en/dev/ref/models/options/#permissions

Câu trả lời:


148

manage.py dumpdata --naturalsẽ sử dụng biểu diễn khóa ngoại bền hơn. Trong django chúng được gọi là "khóa tự nhiên". Ví dụ:

  • Permission.codename được sử dụng để ủng hộ Permission.id
  • User.username được sử dụng để ủng hộ User.id

Đọc thêm: phần khóa tự nhiên trong "tuần tự hóa các đối tượng django"

Một số lập luận hữu ích khác cho dumpdata:

  • --indent=4 làm cho nó có thể đọc được.
  • -e sessions loại trừ dữ liệu phiên
  • -e admin loại trừ lịch sử hành động của quản trị viên trên trang web quản trị
  • -e contenttypes -e auth.Permissionloại trừ các đối tượng được tạo lại tự động khỏi lược đồ mọi lúc syncdb. Chỉ sử dụng nó cùng với --naturalnếu không, bạn có thể kết thúc với các số id được căn chỉnh sai.

1
@skyjur Tại sao luôn sử dụng -e contenttypes -e auth.permissionvới --natural? Tôi chỉ thử mà không có --naturaltùy chọn và nó đã hoạt động. Ngoài ra tài liệu ở đây cho biết người ta nên sử dụng tùy chọn này nếu DUMPING auth.permissioncontenttypes.
wlnirvana

6
@winirvana bởi vì sau khi bạn bắt đầu lại từ đầu và thực hiện syncdb, mới được tạo ContentTypePermissionkhông được đảm bảo nhận được cùng id như trước đây. Kết xuất dữ liệu của bạn chứa các id có thể tham chiếu đến các đối tượng khác nhau trên cơ sở dữ liệu khác nơi bạn sẽ tải dữ liệu. Nó có thể hiệu quả với bạn vì một trong những lý do sau: 1) dữ liệu của bạn không có bất kỳ tham chiếu nào đến các đối tượng này 2) id gốc của Permission / ContentTypes được giữ nguyên 3) dữ liệu tải của bạn thành công nhưng bạn thực sự có dữ liệu bị hỏng do các đối tượng đề cập đến đối tượng sai và bạn chưa biết về nó
Trượt tuyết vào

12
Cờ --naturalhiện không được dùng nữa để ủng hộ --natural-foreign(và --natural-primary)
frnhr

16
Lệnh cuối cùng có thể là:manage.py dumpdata --natural-foreign --natural-primary -e contenttypes -e auth.Permission --indent 4 > project_dump.json
Paolo

4
--naturalhiện đã bị loại bỏ hoàn toàn, không chỉ là không được chấp nhận. Sử dụng --natural-foreignhoặc --natural-primarythay thế.
Code-Apprentice

35

Vâng, điều này thực sự gây khó chịu. Trong một thời gian, tôi đã giải quyết vấn đề này bằng cách thực hiện "đặt lại management.py" trên ứng dụng contenttypes trước khi tải lịch thi đấu (để loại bỏ dữ liệu contenttypes được tạo tự động khác với phiên bản được kết xuất). Điều đó đã hiệu quả, nhưng cuối cùng tôi phát ngán vì sự phức tạp và các đồ đạc bị bỏ rơi hoàn toàn để ủng hộ các kết xuất SQL thẳng (tất nhiên, sau đó bạn mất tính di động của DB).

cập nhật - câu trả lời tốt nhất là sử dụng --naturalcờ dumpdata, như đã lưu ý trong câu trả lời bên dưới. Lá cờ đó vẫn chưa tồn tại khi tôi viết câu trả lời này.


3
Tôi cũng gặp phải vấn đề này, việc đặt lại ứng dụng contenttypes cũng phù hợp với tôi. Cảm ơn vì tiền hỗ trợ!
Beau

Bạn đã thiết lập lại chúng như thế nào? Trong lớp test case? Hãy cho tôi một ví dụ xin
Oleg Tarasenko

4
Tôi không sử dụng đồ đạc cho các đơn vị, tôi thường tạo dữ liệu thử nghiệm bằng cách sử dụng ORM trong phương thức setup () vì nó dễ đồng bộ hóa hơn với các thử nghiệm. Vì vậy, tôi chưa bao giờ phải làm điều này trong lớp TestCase, mặc dù tôi chắc chắn nếu bạn xem qua mã cho lớp TestCase của Django, bạn có thể tìm ra cách thực hiện thiết lập lại sau khi đăng syncdb và trước khi tải cố định trong một lớp con. Đối với tôi, đó chỉ là "./manage.py đặt lại các kiểu nội dung" trong một tập lệnh bash trước "./manage.py loaddata my_fixture".
Carl Meyer

32

Hãy thử bỏ qua các loại nội dung khi tạo lịch thi đấu:

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

Nó hoạt động với tôi trong một tình huống tương tự đối với các bài kiểm tra đơn vị, cái nhìn sâu sắc của bạn về các loại nội dung thực sự hữu ích!


31

Các câu trả lời ở đây đều cũ ... Tính đến năm 2017, câu trả lời tốt nhất là:

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

11

Tôi đã không sử dụng MySQL mà thay vào đó nhập một số dữ liệu từ máy chủ trực tiếp vào sqlite. Xóa contenttypesdữ liệu ứng dụng trước khi thực hiện loaddatađã thực hiện mẹo:

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

Và sau đó

python manage.py loaddata data.json

django.core.exceptions.ImproperlyConfigured: Đã yêu cầu cài đặt INSTALLED_APPS, nhưng cài đặt không được định cấu hình. Bạn phải xác định biến môi trường DJANGO_SETTINGS_MODULE hoặc gọi settings.configure () trước khi truy cập cài đặt.
Barney

Nó có thể hoạt động tốt nhất trong phạm vi xử lý của lệnh quản lý tùy chỉnh.
Barney

10

Tôi đã giải quyết vấn đề này trong các trường hợp thử nghiệm của mình bằng cách đặt lại ứng dụng contenttypes từ thử nghiệm đơn vị trước khi tải tệp kết xuất của tôi. Carl đã đề xuất điều này bằng cách sử dụng manage.pylệnh và tôi làm điều tương tự chỉ bằng cách sử dụng call_commandphương pháp:

>>> 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.jsonVật cố định của tôi chứa kết xuất ứng dụng contenttypes tương ứng với phần còn lại của dữ liệu thử nghiệm. Bằng cách đặt lại ứng dụng trước khi tải, nó ngăn chặn khóa trùng lặp IntegrityError.


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

Điều này làm việc cho tôi. Ở đây tôi loại trừ mọi thứ trên các mô hình thực tế.

  • Nếu bạn thấy bất kỳ mô hình nào khác ngoài các mô hình mà bạn đã tạo, bạn có thể loại trừ chúng một cách an toàn. Một hạn chế của cách tiếp cận này là bạn mất dữ liệu nhật ký cũng như dữ liệu xác thực.

6

Bạn cần sử dụng khóa tự nhiên để đại diện cho bất kỳ khóa ngoại nào và mối quan hệ nhiều-nhiều. Hơn nữa, có thể là một ý kiến ​​hay nếu loại trừ sessionbảng trong sessionsứng dụng và logentrybảng trong adminứng dụng.

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

Theo tài liệu Django , --naturalđã không còn được dùng trong phiên bản 1.7, vì vậy tùy chọn --natural-foreignnày sẽ được sử dụng thay thế.

Bạn cũng có thể bỏ qua khóa chính trong dữ liệu tuần tự hóa của đối tượng này vì nó có thể được tính toán trong quá trình giải mã hóa bằng cách chuyển --natural-primarycờ.

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

sẽ thay đổi

  "content_type": 123

đến

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

Và cố định hoạt động cho TestCasebây giờ


2

Django 2.2.5

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

Nó đã giúp đỡ tôi


Nó sẽ gây ra vấn đề khi tải dữ liệu, có thể không khớp với loại nội dung trong cơ sở dữ liệu mới
yang zhou

1

Tôi sẽ đưa ra một câu trả lời khả thi khác mà tôi vừa mới tìm ra. Có thể nó sẽ giúp OP, có thể nó sẽ giúp ai đó khác.

Tôi có một bảng mối quan hệ nhiều-nhiều. Nó có một khóa chính và hai khóa ngoại cho các bảng khác. Tôi thấy rằng nếu tôi có một mục nhập trong lịch thi đấu có hai khóa ngoại giống với một mục nhập khác đã có trong bảng với pk khác , nó sẽ không thành công. Các bảng quan hệ M2M có một "duy nhất cùng nhau" cho hai khóa ngoại.

Vì vậy, nếu mối quan hệ M2M đang bị phá vỡ, hãy xem các khóa ngoại mà nó thêm vào, xem cơ sở dữ liệu của bạn để xem liệu cặp FK đó đã được liệt kê trong một PK khác chưa.


1

Nó thực sự, thực sự khó chịu .. Tôi bị cắn bởi điều này mỗi lần.

Tôi đã cố gắng kết xuất dữ liệu với - loại trừ các loại nội dung và - tự nhiên, tôi luôn gặp sự cố ..

Điều tốt nhất đối với tôi chỉ đơn giản là làm truncate table django_content_type;sau khi syncdb và SAU ĐÓ tải dữ liệu.

Tất nhiên, đối với tự động điền Initial_data.json, bạn sẽ rất khó chịu.


Đối với tôi, việc cắt bớt bảng trước khi tải dữ liệu chỉ gây ra các lỗi khác nhau. Không có may mắn với kỹ thuật này.
shacker

1

Tôi đã gặp lỗi tương tự đôi khi trước đây. Hóa ra là tôi đang cố gắng tải các đồ đạc trước khi tạo các bảng cần thiết. Tôi cũng vậy:

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

Và nó hoạt động như một cái duyên


0

Trong trường hợp của tôi, tôi đã hủy dữ liệu từ auth( ./manage.py dumpddata auth > fixtures/auth.json) để sử dụng vật cố định cho mục đích thử nghiệm.

Sự phát triển tiếp tục và tôi đã loại bỏ hầu hết các mô hình mà tôi đã xác định models.pyvà đây là lúc tôi bắt đầu thấy vấn đề khó chịu này.

Giải pháp của tôi là tạo lại vật cố định auth.json một lần nữa. Cái này đã xóa rất nhiều mục auth.permissionliên quan đến các mẫu cũ mà tôi có.


0

Tôi đã thử mọi phương pháp từ bên trên, Không có gì hiệu quả với tôi. Tôi phải loại trừ mô hình xác thực hoàn chỉnh và hoạt động tốt.

python manage.py dumpdata --natural-primary --exclude=contenttypes --exclude=auth --exclude=admin.logentry --exclude=sessions.session --indent 4 > live.json
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.