Comment définir un Django modèle du champ valeur par défaut à un appel de fonction / callable (par exemple, une date par rapport à l'heure de modèle de création de l'objet)
ÉDITÉ:
Comment puis-je configurer un Django par défaut d'une rubrique à une fonction qui récupère évalués à chaque fois qu'un nouveau modèle objet est créé?
Je veux faire quelque chose comme ce qui suit, sauf que dans ce code, le code est évaluée une fois et définit la valeur par défaut, à la même date pour chaque modèle objet créé, plutôt que d'évaluer le code à chaque fois qu'un modèle objet 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 la fonction telle qu'elle est dynamique et obtient appelés et mis à chaque fois que la fonction est appelée. Comment puis-je le faire? 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))
- La question est de misworded: il n'a rien à voir avec la fonction de paramètre par défaut. Voir ma réponse.
- Par @NedBatchelder commentaire, j'ai édité ma question (indiqué comme "MODIFIÉ:") et à gauche l'original (indiqué comme "ORIGINAL:")
Vous devez vous connecter pour publier un commentaire.
La question est erronée. Lors de la création d'un modèle de champ dans Django, vous n'êtes pas à la définition d'une fonction, de sorte que la fonction des valeurs par défaut ne sont pas pertinents:
Cette dernière ligne n'est pas la définition d'une fonction; c'est l'appel d'une fonction pour créer un champ dans la classe.
PRÉ Django 1.7
Django vous permet de passer un appelable par défaut, et il va l'appeler à chaque fois, tout 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é (c.f. @stvnw commentaire). La bonne façon de le faire est de déclarer une fonction avant le domaine et l'utiliser comme un objet appelable dans default_value nommé arg:
Plus d'informations dans le @simanas réponse ci-dessous
get_default_my_date
?Faire ce
default=datetime.now()+timedelta(days=1)
est absolument faux!Il obtient évalué lorsque vous démarrez votre instance de django. Si vous êtes sous apache, il fonctionnera probablement, parce que sur certaines configurations apache révoque votre application django, pour chaque demande, mais vous pouvez toujours trouver que vous êtes une personne un jour, en regardant à travers votre code et essayer de comprendre pourquoi cela s'est calculée non pas comme vous l'attendez.
La bonne façon de le faire est de passer un objet appelable à l'argument par défaut. Il peut être un datetime.aujourd'hui, de fonction ou de votre fonction personnalisée. Puis il est évalué à chaque fois que vous demandez une nouvelle valeur par défaut.
get_deadline(my_parameter)
?deadline
champ nouveau, tout aussi la suppression de laget_deadline
fonction? J'ai retiré un champ avec une fonction d'une valeur par défaut, mais maintenant, Django se bloque au démarrage après la suppression de la fonction. J'ai pu modifier manuellement la migration, ce qui serait ok dans ce cas, mais que faire si vous avez simplement changé la valeur par défaut de la fonction, et voulait supprimer l'ancienne fonction?Il y a une distinction importante entre les deux DateTimeField constructeurs:
Si vous utilisez
auto_now_add=True
dans le constructeur, le type datetime référencé par my_date est "immuable" (qu'une seule fois, lorsque la ligne est insérée dans la table).Avec
auto_now=True
, cependant, la valeur de type datetime sera mis à jour chaque fois que l'objet est enregistré.Cela a certainement été un piège pour moi à un moment donné. Pour référence, les docs sont ici:
https://docs.djangoproject.com/en/dev/ref/models/fields/#datetimefield
Vous ne pouvez pas le faire directement; la valeur par défaut est évalué lors de la définition de la fonction est évaluée. Mais il y a deux façons de contourner cela.
Tout d'abord, vous pouvez créer (et puis appel) une nouvelle fonction à chaque fois.
Ou, plus simplement, il suffit d'utiliser une valeur spéciale pour marquer la valeur par défaut. Par exemple:
Si
None
est parfaitement raisonnable de la valeur du paramètre, et il n'y a raisonnablement pas d'autre valeur que vous pourriez utiliser à sa place, il vous suffit de créer une nouvelle valeur qui est certainement en dehors du domaine de votre fonction:Dans certains cas rares, vous êtes en train de rédiger méta-code qui n'a vraiment besoin pour être en mesure de prendre absolument n'importe quoi, même, dit-on,
mydate.func_defaults[0]
. Dans ce cas, vous devez faire quelque chose comme ceci:myfunc
fonction est de faire prendre (et imprimer) undatetime
; vous l'avez changé, il ne peut donc pas être utilisé de cette façon.Parfois, vous devrez peut-être le modèle d'accès des données après la création d'un nouveau modèle d'utilisateur.
Ici est de savoir comment générer un jeton pour chaque nouveau profil d'utilisateur en utilisant les 4 premiers caractères de leur nom d'utilisateur:
Passer de la fonction en tant que paramètre au lieu de passer dans la suite de l'appel de la fonction.
Qui est, au lieu de cela:
Essayez ceci:
print datetime.now()
sans condition.datetime.now
fonction. Mais tout utilisateur qui passe une non-valeur par défaut sera le passage d'un datetime, pas une fonction.foo = datetime.now(); myfunc(foo)
va augmenterTypeError: 'datetime.datetime' object is not callable
. Si je voulais utiliser votre fonction, je dois faire quelque chose commemyfunc(lambda: foo)
au lieu de cela, ce qui n'est pas raisonnable de l'interface.time.strftime
, par exemple, ne prenez pas une fonction qui renvoie une fois, ni n'str.__add__
prendre une fonction qui retourne une chaîne de caractères.models.DateTimeField
interface attend (ou devrait s'attendre) une fonction qui retourne une date, au lieu d'une date?