web-dev-qa-db-fra.com

Écriture d'une fonction __init__ à utiliser dans le modèle Django

J'essaie d'écrire une fonction __init__ Pour l'un de mes modèles afin de pouvoir créer un objet en faisant:

p = User('name','email')

Lorsque j'écris le modèle, j'ai:

def __init__(self, name, email, house_id, password):
    models.Model.__init__(self)
    self.name = name
    self.email = email

Cela fonctionne et je peux enregistrer l'objet dans la base de données, mais quand je fais User.objects.all(), il ne tire rien à moins que je ne retire ma fonction __init__. Des idées?

66
victor

S'appuyer sur la fonctionnalité intégrée de Django et passer des paramètres nommés serait le moyen le plus simple.

p = User(name="Fred", email="[email protected]")

Mais si vous êtes prêt à enregistrer certaines séquences de touches, je suggérerais d'ajouter une méthode de commodité statique à la classe au lieu de jouer avec l'initialiseur.

# In User class declaration
@classmethod
def create(cls, name, email):
  return cls(name=name, email=email)

# Use it
p = User.create("Fred", "[email protected]")
97
Baldu

Django s'attend à ce que la signature du constructeur d'un modèle soit (self, *args, **kwargs), ou un fac-similé raisonnable. Votre modification de la signature en quelque chose de complètement incompatible l'a brisée.

La bonne réponse consiste à éviter de remplacer __init__ et écrivez une méthode de classe comme décrit dans les Django docs .

Mais cela pourrait être fait comme si vous essayiez, il vous suffit d'ajouter *args, **kwargs à accepter par votre __init__, et passez-les à l'appel de la super méthode.

def __init__(self, name, email, house_id, password, *args, **kwargs):
        super(models.Model, self).__init__(self, *args, **kwargs)
        self.name = name
        self.email = email
16
austinheiman

Ne créez pas de modèles avec des paramètres args. Si vous faites un modèle comme ça:

 User('name','email')

Il devient très illisible très rapidement car la plupart des modèles nécessitent plus que cela pour l'initialisation. Vous pourriez très facilement vous retrouver avec:

User('Bert', 'Reynolds', '[email protected]','0123456789','5432106789',....)

Un autre problème ici est que vous ne savez pas si "Bert" est le prénom ou le nom de famille. Les deux derniers numéros peuvent facilement être un numéro de téléphone et un identifiant système. Mais sans que cela soit explicite, vous pourrez les mélanger plus facilement, ou mélanger l'ordre si vous utilisez des identifiants. De plus, le fait de le faire par ordre imposera une autre contrainte aux autres développeurs qui utilisent cette méthode et ne se souviendront pas de l'ordre arbitraire des paramètres.

Vous devriez plutôt préférer quelque chose comme ça:

User(
    first_name='Bert',
    last_name='Reynolds',
    email='[email protected]',
    phone='0123456789',
    system_id='5432106789',
)

Si c'est pour des tests ou quelque chose comme ça, vous pouvez utiliser une usine pour créer rapidement des modèles. Le lien du garçon d'usine peut être utile: http://factoryboy.readthedocs.org/en/latest/

2
unflores