ÉDITÉ:
Comment puis-je définir la valeur par défaut d'un champ Django sur une fonction qui est évaluée chaque fois qu'un nouvel objet modèle est créé?
Je veux faire quelque chose comme ce qui suit, sauf que dans ce code, le code est évalué une fois et définit la valeur par défaut à la même date pour chaque objet de modèle créé, plutôt que d'évaluer le code chaque fois qu'un objet de modèle est créé:
from datetime import datetime, timedelta
class MyModel(models.Model):
# default to 1 day from now
my_date = models.DateTimeField(default=datetime.now() + timedelta(days=1))
ORIGINAL:
Je veux créer une valeur par défaut pour un paramètre de fonction de telle sorte qu'il soit dynamique et qu'il soit appelé et défini à chaque fois que la fonction est appelée. Comment puis je faire ça? par exemple,
from datetime import datetime
def mydate(date=datetime.now()):
print date
mydate()
mydate() # prints the same thing as the previous call; but I want it to be a newer value
Plus précisément, je veux le faire dans Django, par exemple,
from datetime import datetime, timedelta
class MyModel(models.Model):
# default to 1 day from now
my_date = models.DateTimeField(default=datetime.now() + timedelta(days=1))
django
django-models
parameters
lambda
default
Rob Bednark
la source
la source
Réponses:
La question est erronée. Lors de la création d'un champ de modèle dans Django, vous ne définissez pas de fonction, les valeurs par défaut de la fonction ne sont donc pas pertinentes:
Cette dernière ligne ne définit pas une fonction; il appelle une fonction pour créer un champ dans la classe.
PRE Django 1.7
Django vous permet de passer un appelable par défaut , et il l'invoquera à chaque fois, comme vous le souhaitez:
Django 1.7+
Veuillez noter que depuis Django 1.7, l'utilisation de lambda comme valeur par défaut n'est pas recommandée (cf @stvnw commentaire). La bonne façon de faire est de déclarer une fonction avant le champ et de l'utiliser comme appelable dans default_value nommé arg:
Plus d'informations dans la réponse @simanas ci-dessous
la source
get_default_my_date
?Faire cela
default=datetime.now()+timedelta(days=1)
est absolument faux!Il est évalué lorsque vous démarrez votre instance de django. Si vous êtes sous Apache, cela fonctionnera probablement, car sur certaines configurations, Apache révoque votre application django à chaque demande, mais vous pouvez quand même vous retrouver un jour en train de parcourir votre code et d'essayer de comprendre pourquoi cela n'est pas calculé comme prévu .
La bonne façon de faire est de passer un objet appelable à l'argument par défaut. Il peut s'agir d'une fonction datetime.today ou de votre fonction personnalisée. Ensuite, il est évalué chaque fois que vous demandez une nouvelle valeur par défaut.
la source
get_deadline(my_parameter)
?deadline
nouveau le champ tout en supprimant également laget_deadline
fonction? J'ai supprimé un champ avec une fonction pour une valeur par défaut, mais maintenant Django plante au démarrage après avoir supprimé la fonction. Je pourrais modifier manuellement la migration, ce qui serait correct dans ce cas, mais que se passerait-il si vous changiez simplement la fonction par défaut et que vous vouliez supprimer l'ancienne fonction?Il existe une distinction importante entre les deux constructeurs DateTimeField suivants:
Si vous utilisez
auto_now_add=True
dans le constructeur, la date / heure référencée par my_date est "immuable" (définie une seule fois lorsque la ligne est insérée dans la table).Avec
auto_now=True
, cependant, la valeur datetime sera mise à jour à chaque fois que l'objet est enregistré.C'était définitivement un piège pour moi à un moment donné. Pour référence, les documents sont ici:
https://docs.djangoproject.com/en/dev/ref/models/fields/#datetimefield
la source
Parfois, vous devrez peut-être accéder aux données du modèle après avoir créé un nouveau modèle utilisateur.
Voici comment je génère un jeton pour chaque nouveau profil d'utilisateur en utilisant les 4 premiers caractères de leur nom d'utilisateur:
la source
Vous ne pouvez pas faire cela directement; la valeur par défaut est évaluée lors de l'évaluation de la définition de fonction. Mais il y a deux façons de contourner cela.
Tout d'abord, vous pouvez créer (puis appeler) une nouvelle fonction à chaque fois.
Ou, plus simplement, utilisez simplement une valeur spéciale pour marquer la valeur par défaut. Par exemple:
Si
None
est une valeur de paramètre parfaitement raisonnable, et qu'il n'y a pas d'autre valeur raisonnable que vous pourriez utiliser à sa place, vous pouvez simplement créer une nouvelle valeur qui est définitivement en dehors du domaine de votre fonction:Dans certains cas rares, vous êtes méta-écriture de code qui fait vraiment besoin d'être en mesure de prendre absolument rien, même, disons,
mydate.func_defaults[0]
. Dans ce cas, vous devez faire quelque chose comme ceci:la source
myfunc
fonction est faite pour prendre (et imprimer) undatetime
; vous l'avez changé pour ne pas l'utiliser de cette façon.Passez la fonction en tant que paramètre au lieu de transmettre le résultat de l'appel de fonction.
Autrement dit, au lieu de ceci:
Essaye ça:
la source
print datetime.now()
sans condition.datetime.now
fonction. Mais tout utilisateur qui transmet une valeur autre que celle par défaut transmettra une date / heure, pas une fonction.foo = datetime.now(); myfunc(foo)
augmenteraTypeError: 'datetime.datetime' object is not callable
. Si je voulais réellement utiliser votre fonction, je devrais faire quelque chose comme à lamyfunc(lambda: foo)
place, ce qui n'est pas une interface raisonnable.