Obtention de TypeError: __init __ () manque 1 argument de position requis: 'on_delete' lors de la tentative d'ajout de table parent après la table enfant avec des entrées


92

J'ai deux classes dans ma base de données sqlite, une table parent nommée Categorieet la table enfant appelée Article. J'ai créé d'abord la classe de table enfant et ajoute des entrées. Alors j'ai d'abord eu ceci:

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

Et après avoir ajouté la table parent, et maintenant mon models.pyressemble à ceci:

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

Donc, quand je cours python manage.py makemigrations <my_app_name>, j'obtiens cette erreur:

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'

J'ai vu des problèmes similaires dans stackoverflow, mais cela ne semble pas être le même problème: __init __ () manque 1 argument positionnel requis: 'quantité'


3
quelle version de django utilisez-vous?
alfonso.kim

2
Alors, de quoi êtes-vous confus ici? Comme l'erreur dit clairement, ForeignKey a un argument nécessaire, on_delete. Consultez la documentation .
Daniel Roseman

Je n'ai pas besoin du on_deleteparamètre, est-ce obligatoire?
Christian Lisangola

@ jochri3 Oui, l' argument positionnel requis signifie qu'il est obligatoire. Consultez la documentation pour savoir quelle option correspond le mieux à vos besoins.
cezar

Réponses:


168

Vous pouvez modifier la propriété categoriede la classe Articlecomme ceci:

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

et l'erreur devrait disparaître.

Finalement, vous pourriez avoir besoin d'une autre option pour on_delete, consultez la documentation pour plus de détails:

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

ÉDITER:

Comme vous l'avez indiqué dans votre commentaire, pour lequel vous n'avez pas d'exigences particulières on_delete, vous pouvez utiliser l'option DO_NOTHING:

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

1
on_delete = models.CASCADE est la valeur par défaut dans Django <2
Peter F

46

Depuis Django 2.x, on_deleteest requis.

Documentation Django

Obsolète depuis la version 1.9: on_delete deviendra un argument obligatoire dans Django 2.0. Dans les anciennes versions, la valeur par défaut est CASCADE.


11

De Django 2.0 on_deleteest requis:

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

Il supprimera les données de la table enfant si l'utilisateur est supprimé. Pour plus de détails, consultez la documentation de Django.


1
Pourquoi cette réponse alors qu'Andrey a répondu plus tôt avec cette information?
Samuel Dauzon

11

Depuis Django 2.0, le champ ForeignKey nécessite deux arguments positionnels:

  1. le modèle auquel mapper
  2. l'argument on_delete
categorie = models.ForeignKey('Categorie', on_delete=models.PROTECT)

Voici quelques méthodes utilisables dans on_delete

  1. CASCADE

Cascade supprime. Django émule le comportement de la contrainte SQL ON DELETE CASCADE et supprime également l'objet contenant le ForeignKey

  1. PROTÉGER

Empêchez la suppression de l'objet référencé en levant ProtectedError, une sous-classe de django.db.IntegrityError.

  1. NE FAIS RIEN

Ne pas agir. Si votre backend de base de données applique l'intégrité référentielle, cela provoquera une erreur IntegrityError sauf si vous ajoutez manuellement une contrainte SQL ON DELETE au champ de base de données.

vous pouvez en savoir plus sur on_delete en lisant la documentation .


4

Si vous utilisez une clé étrangère, vous devez utiliser "on_delete = models.CASCADE" car cela éliminera la complexité développée après la suppression de l'élément d'origine de la table parent. Aussi simple que cela.

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

3

Voici les options disponibles si cela aide quelqu'un pour on_delete

CASCADE, DO_NOTHING, PROTECT, SET, SET_DEFAULT, SET_NULL


1

Post Django version 1.9, on_deleteest devenu un argument obligatoire, c'est à dire à partir de Django 2.0.

Dans les anciennes versions, il était par défaut CASCADE.

Donc, si vous souhaitez répliquer la fonctionnalité que vous avez utilisée dans les versions antérieures. Utilisez l'argument suivant.

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

Cela aura le même effet que dans les versions précédentes , sans le spécifier explicitement.

Documentation officielle sur les autres arguments associés à on_delete


0

Si vous ne savez pas quelle option entrer les paramètres. Je veux simplement conserver la valeur par défaut comme on_delete=Noneavant la migration:

on_delete = models.CASCADE

Ceci est un extrait de code dans l'ancienne version:

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

Un problème similaire a été résolu en ajoutant ces deux paramètres à ForeignKey: null = True, on_delete = models.SET_NULL


-3

Cela a fonctionné pour moi pip install django-csvimport --upgrade


2
Comment cela répond-il à la question?
cezar

Salut Mayank. Vous avez probablement fait autre chose pour corriger cette erreur ou vous utilisez une version antérieure de django.
Chris Dare

Ceci est résolu en fournissant une valeur pour l'argument « on_delete » à models.ForeignKey
Chris Dare

Vous utilisez Django avant la version 2. Parce que toutes les versions ultérieures ont créé on_deleteune contrainte! Par défaut dans les versions antérieures, c'étaiton_delete = models.CASCADE
Optider le
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.