2017-06-29 2 views
1

***** Travailler avec Django 1.11.x et Python 3.6 *****Utilisation de la méthode save() dans le modèle Django produit TypeError

J'essaie d'apprendre à utiliser la sauvegarde() dans un modèle Django (models.py). Il y a deux champs ici que je veux devenir personnalisés, les champs 'calculés' (unique_id et age).

D'abord, j'initier les variables de champ, puis définissez les méthodes/propriétés basées sur les champs existants, puis j'essaie de sauvegarder les résultats de la méthode dans les champs que j'ai créé.

from django.db import models 
from dateutil.relativedelta import relativedelta 
from datetime import datetime 

class Person(models.Model): 
    unique_id = models.CharField(max_length=6, primary_key=True) 
    age = models.IntegerField() 
    last_name = models.CharField(max_length=25) 
    birth_date = models.DateField() 
    city_of_birth = models.CharField(max_length=25) 

    @property 
    def get_unique_id(self): 
     a = self.last_name[:2].upper()  #First 2 letters of last name 
     b = self.birth_date.strftime('%d')  #Day of the month as string 
     c = self.city_of_birth[:2].upper()  #First 2 letters of city 
     return a + b + c 

    @property 
    def get_age(self): 
     return relativedelta(self.birth_date.days, datetime.date.now()).years 

    def save(self, *args, **kwarg): 
     self.unique_id = self.get_unique_id() 
     self.age = self.get_age() 
     super(Person, self).save(*args, **kwarg) 

    def __str__(self): 
     return self.unique_id 

D'abord, je crée 5 champs. Deux d'entre eux sont des espaces réservés: unique_id et age. Ensuite, je définis deux méthodes @property et chacune renvoie un type de résultat différent. La fonction "get_unique_id" fonctionne, mais je ne peux pas obtenir le résultat stocké dans la base de données. La fonction "get_age" peut ou peut ne pas fonctionner. Je n'ai pas encore pu le produire.

Ma première question est de savoir comment utiliser correctement la sauvegarde() pour remplacer les valeurs de champ initiales (id_unique et âge) avec mes méthodes « de champ calculé » (get_unique_id et get_age) .

Mon principal problème est que lorsque j'ajouter une personne (en utilisant la personne ModelForm dans/Admin), il produit un TypeError:objet « str » est pas appelable à la ligne "self.unique_id = self.get_unique_id() ". J'utilise actuellement l'interface d'administration pour tester.

Finalement, je dois apprendre à afficher PAS ces 2 champs dans les formes, car ils seront calculés sur la base des autres champs. Je pense que j'ai peut-être trouvé de la documentation sur Meta qui pourrait aider. En outre, je veux que le champ unique_id soit la clé primaire, j'ai donc ajouté cette option au champ initial.

J'ai une question secondaire (mes excuses pour être à nouveau Django) sur les * args et ** kwargs. Est-ce bon de les laisser là? Je ne suis pas sûr de savoir quels arguments je dois utiliser, le cas échéant, et si oui ou non il est nécessaire d'inclure * args et ** kwargs dans le code.

NOTE: Pour toute personne qui m'a aidé hier avec cette application, j'apprécie vraiment votre aide. Je considère que ceci est différent de ma question précédente, bien que j'utilise beaucoup du même code.

+0

Ne faites pas cela. Il est inutile de définir l'âge comme un champ distinct, car il deviendra obsolète. Calculez-le quand vous en avez besoin. –

+0

D'accord, merci. Je peux vivre avec cela.L'unique_id est le plus important. –

Répondre

2

propriétés ne sont pas remboursables par anticipation. Lorsque vous accédez à self.get_unique_id, Python appelle la méthode sous-jacente décorée par @property dans les coulisses, ce qui dans ce cas renvoie une chaîne. Vous n'avez pas besoin de l'appeler à nouveau, laissez tomber les parens:

def save(self, *args, **kwarg): 
    self.unique_id = self.get_unique_id 
    self.age = self.get_age 
    super(Person, self).save(*args, **kwarg) 

OTOH, en passant par le commentaire de @ DanielRoseman, vous n'avez pas besoin de stocker l'âge dans la base de données. Il suffit de le calculer quand c'est nécessaire. Vous pouvez renommer get_age comme age et déposez le champ age, donc age devient une propriété.

+0

CECI TRAVAILLÉ! Je vous remercie. –

+0

@RonRaney Vous pouvez envisager d'accepter la réponse si elle a aidé –

+0

Je suis moins de 15 avis donc ils n'aiment pas mon avis :) –