Bắt lỗi TypeError: __init __ () thiếu 1 đối số vị trí bắt buộc: 'on_delete' khi cố gắng thêm bảng mẹ sau bảng con có các mục nhập


92

Tôi có hai lớp trong cơ sở dữ liệu sqlite của mình, một bảng cha được đặt tên Categorievà bảng con được gọi Article. Đầu tiên tôi tạo lớp bảng con và thêm các mục nhập. Vì vậy, đầu tiên tôi có cái này:

class Article(models.Model):
    titre=models.CharField(max_length=100)
    auteur=models.CharField(max_length=42)
    contenu=models.TextField(null=True)
    date=models.DateTimeField(
        auto_now_add=True,
        auto_now=False,
        verbose_name="Date de parution"
    )

    def __str__(self):
        return self.titre

Và sau khi tôi đã thêm bảng cha và bây giờ của tôi models.pytrông như thế này:

from django.db import models

# Create your models here.
class Categorie(models.Model):
    nom = models.CharField(max_length=30)

    def __str__(self):
        return self.nom


class Article(models.Model):
    titre=models.CharField(max_length=100)
    auteur=models.CharField(max_length=42)
    contenu=models.TextField(null=True)
    date=models.DateTimeField(
        auto_now_add=True,
        auto_now=False,
        verbose_name="Date de parution"
    )
    categorie = models.ForeignKey('Categorie')

    def __str__(self):
        return self.titre

Vì vậy, khi tôi chạy python manage.py makemigrations <my_app_name>, tôi gặp lỗi này:

Traceback (most recent call last):
  File "manage.py", line 15, in <module>
    execute_from_command_line(sys.argv)
  File "C:\Users\lislis\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django-2.0-py3.5.egg\django\core\management\__init__.py", line 354, in execute_from_command_line
    utility.execute()
  File "C:\Users\lislis\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django-2.0-py3.5.egg\django\core\management\__init__.py", line 330, in execute
    django.setup()
  File "C:\Users\lislis\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django-2.0-py3.5.egg\django\__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "C:\Users\lislis\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django-2.0-py3.5.egg\django\apps\registry.py", line 112, in populate
    app_config.import_models()
  File "C:\Users\lislis\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django-2.0-py3.5.egg\django\apps\config.py", line 198, in import_models
    self.models_module = import_module(models_module_name)
  File "C:\Users\lislis\AppData\Local\Programs\Python\Python35-32\lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 665, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "C:\Users\lislis\Django\mon_site\blog\models.py", line 6, in <module>
    class Article(models.Model):
  File "C:\Users\lislis\Django\mon_site\blog\models.py", line 16, in Article
    categorie = models.ForeignKey('Categorie')
TypeError: __init__() missing 1 required positional argument: 'on_delete'

Tôi đã gặp một số vấn đề tương tự trong stackoverflow, nhưng có vẻ như không phải là vấn đề tương tự: __init __ () thiếu 1 đối số vị trí bắt buộc: 'số lượng'


3
bạn đang sử dụng phiên bản django nào?
alfonso.kim

2
Vì vậy, bạn đang bối rối về điều gì ở đây? Như lỗi đã nói rõ ràng, ForeignKey có một đối số bắt buộc on_delete,. Xem tài liệu .
Daniel Roseman

Tôi không cần on_deletetham số, nó có bắt buộc không?
Christian Lisangola

@ jochri3 Có, đối số vị trí bắt buộc có nghĩa là nó bắt buộc. Kiểm tra tài liệu để tìm ra tùy chọn phù hợp nhất với nhu cầu của bạn.
cezar

Câu trả lời:


168

Bạn có thể thay đổi thuộc tính categoriecủa lớp Articlenhư sau:

categorie = models.ForeignKey(
    'Categorie',
    on_delete=models.CASCADE,
)

và lỗi sẽ biến mất.

Cuối cùng, bạn có thể cần một tùy chọn khác on_delete, hãy kiểm tra tài liệu để biết thêm chi tiết:

https://docs.djangoproject.com/en/1.11/ref/models/fields/#django.db.models.ForeignKey

BIÊN TẬP:

Như bạn đã nêu trong nhận xét của mình, rằng bạn không có bất kỳ yêu cầu đặc biệt nào on_delete, bạn có thể sử dụng tùy chọn DO_NOTHING:

# ...
on_delete=models.DO_NOTHING,
# ...

1
on_delete = models.CASCADE là mặc định trong Django <2
Peter F

46

Kể từ Django 2.x, on_deletelà bắt buộc.

Tài liệu Django

Không được chấp nhận kể từ phiên bản 1.9: on_delete sẽ trở thành đối số bắt buộc trong Django 2.0. Trong các phiên bản cũ hơn, nó mặc định là CASCADE.


11

Từ Django 2.0 on_deletelà bắt buộc:

user = models.OneToOneField (Người dùng, on_delete = models.CASCADE)

Nó sẽ xóa dữ liệu bảng con nếu Người dùng bị xóa. Để biết thêm chi tiết, hãy kiểm tra tài liệu Django.


1
Tại sao lại trả lời như vậy trong khi Andrey phản hồi trước đó với thông tin này?
Samuel Dauzon

11

Vì Django 2.0 nên trường ForeignKey yêu cầu hai đối số vị trí:

  1. mô hình để ánh xạ
  2. đối số on_delete
categorie = models.ForeignKey('Categorie', on_delete=models.PROTECT)

Dưới đây là một số phương pháp có thể được sử dụng trong on_delete

  1. CASCADE

Xếp tầng xóa. Django mô phỏng hành vi của ràng buộc SQL TRÊN XÓA CASCADE và cũng xóa đối tượng có chứa ForeignKey

  1. BẢO VỆ

Ngăn chặn việc xóa đối tượng được tham chiếu bằng cách nâng cao ProtectedError, một lớp con của django.db.IntegrityError.

  1. KHÔNG LÀM GÌ CẢ

Đừng làm gì cả. Nếu phần phụ trợ cơ sở dữ liệu của bạn thực thi tính toàn vẹn tham chiếu, điều này sẽ gây ra Lỗi IntegrityError trừ khi bạn thêm ràng buộc SQL ON DELETE vào trường cơ sở dữ liệu theo cách thủ công.

bạn có thể tìm thêm về on_delete bằng cách đọc tài liệu .


4

Nếu bạn đang sử dụng khóa ngoại thì bạn phải sử dụng "on_delete = models.CASCADE" vì nó sẽ loại bỏ độ phức tạp được phát triển sau khi xóa phần tử gốc khỏi bảng mẹ. Đơn giản vậy thôi.

categorie = models.ForeignKey('Categorie', on_delete=models.CASCADE)

3

Dưới đây là các tùy chọn có sẵn nếu nó giúp ích cho bất kỳ ai cho on_delete

CASCADE, DO_NOTHING, PROTECT, SET, SET_DEFAULT, SET_NULL


1

Đăng Django phiên bản 1.9, on_deletetrở thành đối số bắt buộc, tức là từ Django 2.0.

Trong các phiên bản cũ hơn, nó mặc định là CASCADE.

Vì vậy, nếu bạn muốn sao chép chức năng mà bạn đã sử dụng trong các phiên bản trước đó. Sử dụng đối số sau đây.

categorie = models.ForeignKey('Categorie', on_delete = models.CASCADE)

Điều này sẽ có tác dụng tương tự như trong các phiên bản trước , mà không chỉ định rõ ràng.

Tài liệu chính thức về các đối số khác đi kèm với on_delete


0

Nếu bạn không biết tùy chọn nào để nhập các tham số. Chỉ muốn giữ giá trị mặc định như on_delete=Nonetrước khi di chuyển:

on_delete = models.CASCADE

Đây là đoạn mã trong phiên bản cũ:

if on_delete is None:
    warnings.warn(
        "on_delete will be a required arg for %s in Django 2.0. Set "
        "it to models.CASCADE on models and in existing migrations "
        "if you want to maintain the current default behavior. "
        "See https://docs.djangoproject.com/en/%s/ref/models/fields/"
        "#django.db.models.ForeignKey.on_delete" % (
            self.__class__.__name__,
            get_docs_version(),
        ),
        RemovedInDjango20Warning, 2)
    on_delete = CASCADE

0

Đã gặp sự cố tương tự được giải quyết bằng cách thêm cả hai tham số này vào ForeignKey: null = True, on_delete = models.SET_NULL


-3

Điều này đã làm việc cho tôi pip install django-csvimport --upgrade


2
Làm thế nào để trả lời câu hỏi này?
cezar

Xin chào Mayank. Có thể bạn đã làm gì đó khác để sửa lỗi đó hoặc bạn đang sử dụng phiên bản django cũ hơn.
Chris Dare

Điều này được giải quyết bằng cách cung cấp giá trị cho đối số "on_delete" cho các mô hình. ForeignKey
Chris Dare

Bạn đang sử dụng Django trước phiên bản 2. Bởi vì tất cả các bản phát hành sau này đều bị on_deletebắt buộc! Theo mặc định trong các phiên bản trước, nó làon_delete = models.CASCADE
Optider
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.