132 votes

Obtention de TypeError : __init__() missing 1 required positional argument : 'on_delete' when trying to add parent table after child table with entries

J'ai deux classes dans ma base de données sqlite, une table parente nommée Categorie et la table enfant appelée Article . J'ai d'abord créé la classe de table enfant et ajouté des entrées. J'avais donc d'abord 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 ma models.py ressemble à ça :

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 j'exécute 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 sur stackoverflow, mais il semble que ce ne soit pas le même problème : __init__() manque 1 argument positionnel requis : 'quantity'.

3 votes

Quelle version de django utilisez-vous ?

3 votes

Alors, qu'est-ce qui vous trouble ici ? Comme l'indique clairement l'erreur, ForeignKey a un argument obligatoire, on_delete . Voir les docs .

0 votes

Je n'ai pas besoin de la on_delete paramètre, est-il obligatoire ?

228voto

cezar Points 1614

Vous pouvez modifier la propriété categorie de la classe Article comme ça :

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

et l'erreur devrait disparaître.

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

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

EDIT :

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

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

3 votes

On_delete=models.CASCADE est la valeur par défaut dans Django < 2

50voto

Andrey Zhilyakov Points 464

Depuis Django 2.x, on_delete est nécessaire.

Documentation sur Django

Déprécié 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.

14voto

Javed Gouri Points 104

De Django 2.0 on_delete est nécessaire :

utilisateur = 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.

2 votes

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

10voto

Alex Jolig Points 466

Jusqu'à Django 1.9, un modèle pouvait ressembler à ce qui suit :

from django.db import models
class Article(models.Model):
    category = models.ForeignKey(Category)
    title =  models.CharField(max_length=55)
    # ...

    def __str__(self):
        return self.title

Clé étrangère est un champ Django permettant de définir une relation de plusieurs à un.

Jusqu'à la version 1.9 de Django, le champ ForeignKey ne nécessitait qu'un seul argument : le modèle auquel il devait être associé.

Depuis Django 2.0 le site Clé étrangère champ requiert deux arguments positionnels :

1- le modèle à mettre en correspondance avec

2 - l'argument on_delete

Pour une correction rapide de "missing 1 required positional argument : on_delete", mettez à jour le modèle :

from django.db import models
class Article(models.Model):
    category = models.ForeignKey('Category', on_delete=models.PROTECT)
    title =  models.CharField(max_length=55)
    # ...

    def __str__(self):
        return self.title

Après avoir corrigé ForeignKey, vous serez en mesure d'exécuter des migrations sans aucun problème :

python manage.py migrate

Merci à Valentino

4voto

Bala Kiswe Points 61

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

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X