Отримання TypeError: __init __ () відсутній 1 необхідний позиційний аргумент: 'on_delete' при спробі додати батьківську таблицю після дочірньої таблиці із записами


92

У моїй базі даних sqlite є два класи, батьківська таблиця з іменем Categorieта дочірня таблиця, яку називають Article. Я створив спочатку клас дочірньої таблиці та додав записи. Отже, спочатку у мене було таке:

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

І після того, як я додав батьківську таблицю, і тепер моя models.pyвиглядає так:

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

Отже, коли я запускаю python manage.py makemigrations <my_app_name>, я отримую таку помилку:

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'

Я бачив деякі подібні проблеми у stackoverflow, але, схоже, це не та сама проблема: __init __ () відсутній 1 необхідний позиційний аргумент: 'кількість'


3
яку версію django ви використовуєте?
alfonso.kim

2
То що вас тут бентежить? Як помилка ясно говорить, ForeignKey має обов'язковий аргумент on_delete. Перегляньте документи .
Даніель Роузман,

Мені не потрібен on_deleteпараметр, чи є він обов'язковим?
Крістіан Лісангола,

@ jochri3 Так, обов’язковий позиційний аргумент означає, що він є обов’язковим. Перевірте документацію, щоб дізнатись, який варіант найкраще відповідає вашим потребам.
cezar

Відповіді:


169

Ви можете змінити властивість categorieкласу Articleтак:

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

і помилка повинна зникнути.

Врешті-решт вам може знадобитися інший варіант on_delete, перевірте документацію для отримання додаткової інформації:

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

РЕДАГУВАТИ:

Як ви зазначили у своєму коментарі, що у вас немає особливих вимог on_delete, ви можете використовувати опцію DO_NOTHING:

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

1
on_delete = models.CASCADE за замовчуванням у Django <2
Peter F


11

З Django 2.0 on_deleteпотрібно:

user = models.OneToOneField (User, on_delete = models.CASCADE)

Дані дочірньої таблиці буде видалено, якщо Користувача буде видалено. Для отримання додаткової інформації перевірте документацію Django.


1
Чому ця відповідь, а Андрій відповів раніше цією інформацією?
Семюель Даузон,

11

Починаючи з Django 2.0, поле ForeignKey вимагає двох позиційних аргументів:

  1. модель для відображення
  2. аргумент on_delete
categorie = models.ForeignKey('Categorie', on_delete=models.PROTECT)

Ось деякі методи, які можна використовувати в on_delete

  1. КАСКАД

Каскад видаляє. Django емулює поведінку обмеження SQL НА ВИДАЛЕННЯ КАСКАДУ, а також видаляє об'єкт, що містить ForeignKey

  1. ЗАХИСТ

Запобігання видаленню об’єкта, на який посилається, підняттям ProtectedError, підкласу django.db.IntegrityError.

  1. НІЧОГО НЕ РОБИТИ

Нічого не вживайте. Якщо ваша внутрішня база даних застосовує цілісність посилань, це призведе до помилки IntegrityError, якщо ви вручну не додасте обмеження SQL ON DELETE до поля бази даних.

Ви можете дізнатись більше про on_delete, прочитавши документацію .


4

Якщо ви використовуєте чужий ключ, то вам доведеться використовувати "on_delete = models.CASCADE", оскільки це усуне складність, що розвинулася після видалення вихідного елемента з батьківської таблиці. Так просто.

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

3

Ось доступні варіанти, якщо це допомагає комусь для on_delete

КАСКАД, НЕ ЗРОБИТИ, ЗАХИСТИТИ, ВСТАНОВИТИ, ВСТАНОВИТИ_ДЕТАЛЬНІ, ВСТАНОВИТИ


1

Повідомлення Django версії 1.9 on_deleteстало необхідним аргументом, тобто з Django 2.0.

У старих версіях за замовчуванням використовується КАСКАД.

Отже, якщо ви хочете відтворити функціонал, який ви використовували в попередніх версіях. Використовуйте наступний аргумент.

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

Це матиме той самий ефект, що й у попередніх версіях , без явного вказівки.

Офіційна документація щодо інших аргументів, які поєднуються з on_delete


0

Якщо ви не знаєте, який варіант ввести параметри. Просто хочу зберегти значення за замовчуванням, як on_delete=Noneперед міграцією:

on_delete = models.CASCADE

Це фрагмент коду у старій версії:

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

Виникла подібна проблема, яка вирішилася шляхом додавання обох цих параметрів до ForeignKey: null = True, on_delete = models.SET_NULL


-3

Це спрацювало для мене pip install django-csvimport --upgrade


2
Як це відповідає на питання?
cezar

Привіт Маянку. Можливо, ви зробили щось інше, щоб виправити цю помилку, або ви використовуєте попередню версію django.
Кріс Дейр

Це вирішується шляхом надання значення аргументу "on_delete" моделям. ForeignKey
Кріс Дейр

Ви використовуєте Django до версії 2. Оскільки всі наступні випуски on_deleteвимагають примусу! За замовчуванням у попередніх версіях це булоon_delete = models.CASCADE
Optider
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.