Obtendo TypeError: __init __ () faltando 1 argumento posicional obrigatório: 'on_delete' ao tentar adicionar uma tabela pai após a tabela filho com entradas

100

Eu tenho duas classes em meu banco de dados sqlite, uma tabela pai chamada Categoriee a tabela filho chamada Article. Criei primeiro a classe da tabela filha e adicionei entradas. Então, primeiro eu tinha isso:

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

E depois de adicionar a tabela pai, agora minha models.pyaparência fica assim:

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

Então, quando eu corro python manage.py makemigrations <my_app_name>, recebo este erro:

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'

Eu vi alguns problemas semelhantes no stackoverflow, mas parece não ser o mesmo problema: __init __ () faltando 1 argumento posicional obrigatório: 'quantidade'

Christian Lisangola
fonte
3
qual versão do django você está usando?
alfonso.kim
2
Então, o que você está confuso aqui? Como o erro diz claramente, ForeignKey tem um argumento obrigatório on_delete,. Veja a documentação .
Daniel Roseman de
Não preciso do on_deleteparâmetro, é obrigatório?
Christian Lisangola
@ jochri3 Sim, o argumento posicional requerido significa que é obrigatório. Verifique a documentação para descobrir qual opção se ajusta melhor às suas necessidades.
cezar

Respostas:

178

Você pode alterar a propriedade categorieda classe Articleassim:

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

e o erro deve desaparecer.

Eventualmente, você pode precisar de outra opção para on_delete, verifique a documentação para obter mais detalhes:

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

EDITAR:

Como você declarou em seu comentário, que não possui requisitos especiais para on_delete, você pode usar a opção DO_NOTHING:

# ...
on_delete=models.DO_NOTHING,
# ...
Cezar
fonte
1
on_delete = models.CASCADE é o padrão no Django <2
Peter F
47

Desde Django 2.x, on_deleteé necessário.

Documentação Django

Obsoleto desde a versão 1.9: on_delete se tornará um argumento obrigatório no Django 2.0. Em versões anteriores, o padrão é CASCADE.

Andrey Zhilyakov
fonte
13

Do Django 2.0 on_deleteé necessário:

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

Ele excluirá os dados da tabela filho se o usuário for excluído. Para mais detalhes, verifique a documentação do Django.

Javed Gouri
fonte
1
Por que essa resposta enquanto Andrey respondeu antes com essa informação?
Samuel Dauzon
11

Desde o Django 2.0, o campo ForeignKey requer dois argumentos posicionais:

  1. o modelo para mapear
  2. o argumento on_delete
categorie = models.ForeignKey('Categorie', on_delete=models.PROTECT)

Aqui estão alguns métodos que podem ser usados ​​em on_delete

  1. CASCATA

Exclusões em cascata. O Django emula o comportamento da restrição SQL ON DELETE CASCADE e também deleta o objeto que contém a ForeignKey

  1. PROTEGER

Evite a exclusão do objeto referenciado levantando ProtectedError, uma subclasse de django.db.IntegrityError.

  1. FAZER NADA

Não faça nada. Se o back-end do banco de dados impõe integridade referencial, isso causará um IntegrityError, a menos que você adicione manualmente uma restrição SQL ON DELETE ao campo do banco de dados.

você pode encontrar mais sobre on_delete lendo a documentação .

Assimitha Deepal
fonte
4

Se você estiver usando a chave estrangeira, você deve usar "on_delete = models.CASCADE", pois isso eliminará a complexidade desenvolvida após a exclusão do elemento original da tabela pai. Tão simples como isso.

categorie = models.ForeignKey('Categorie', on_delete=models.CASCADE)
Bala Kiswe
fonte
3

Aqui estão as opções disponíveis se ajudar alguém para on_delete

CASCADE, DO_NOTHING, PROTECT, SET, SET_DEFAULT, SET_NULL

Tarun Behal
fonte
1

Post Django versão 1.9, on_deletetornou-se um argumento obrigatório, ou seja, do Django 2.0.

Em versões anteriores, o padrão é CASCADE.

Portanto, se você deseja replicar a funcionalidade que você usou nas versões anteriores. Use o seguinte argumento.

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

Isso terá o mesmo efeito que nas versões anteriores , sem especificá-lo explicitamente.

Documentação oficial sobre outros argumentos que acompanham on_delete

Optider
fonte
0

Se você não sabe qual opção inserir os parâmetros. Só quero manter o valor padrão como on_delete=Noneantes da migração:

on_delete = models.CASCADE

Este é um snippet de código na versão antiga:

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
HoangYell
fonte
0

Tive um problema semelhante que foi resolvido adicionando esses dois parâmetros a ForeignKey: null = True, on_delete = models.SET_NULL

Nir Tsabar
fonte
-3

Isso funcionou para mim pip install django-csvimport --upgrade

Mayank Jaiswal
fonte
2
Como isso responde à pergunta?
cezar de
Oi Mayank. Você provavelmente fez outra coisa para corrigir esse erro ou está usando uma versão anterior do django.
Chris Dare
Isso é resolvido fornecendo um valor para o argumento "on_delete" para models.ForeignKey
Chris Dare
Você está usando o Django anterior à versão 2. Porque todas as versões posteriores tornaram-se on_deleteuma compulsão! Por padrão nas versões anteriores, eraon_delete = models.CASCADE
Optider