Je suis en train de mettre à jour mon projet de Django 1.8.2 à 1.9.7 et je reçois cet avertissement:
WARNINGS:
my_app.my_model.date_available: (fields.W161) Fixed default value provided.
HINT: It seems you set a fixed date / time / datetime value as default for this field. This may not be what you want.
If you want to have the current date as default, use `Django.utils.timezone.now
Voici la ligne de my_app/models.py:
from Django.utils import timezone
...
class my_model(models.Model):
...
datetime_released = models.DateTimeField(default=timezone.now() )
Si je supprime les parenthèses et utilise à la place:
datetime_released = models.DateTimeField(default=timezone.now )
L'avertissement Django disparaît. Quelle est la différence entre les deux?
Dans une autre zone de mon projet, j'utilise timezone.now () dans un filtre d'ensemble de requêtes:
def date_available(self):
return self.filter(date_available__lte = timezone.now())
Ici, si je supprime les parenthèses, une erreur est levée:
TypeError: expected string or buffer
Je peux obtenir ces deux travaux en ajoutant/supprimant les parenthèses selon les besoins, mais quelle est la différence entre timezone.now()
et timezone.now
Et pourquoi provoquent-ils des avertissements/erreurs dans ces cas?
Dans python tout est un objet, y compris les fonctions. Cela signifie que vous pouvez affecter une fonction à une variable:
>>> from Django.utils import timezone
>>> foo = timezone.now
>>> foo
<function Django.utils.timezone.now>
>>> foo()
datetime.datetime(2016, 7, 7, 9, 11, 6, 489063)
Une fonction est un objet appelable:
>>> callable(foo)
True
>>> callable(foo())
False
Lorsque default
reçoit un appelable, l'appelable est appelé chaque fois qu'une valeur par défaut est demandée.
En revanche, lorsque vous appelez timezone.now()
avant de définir default
, la valeur est donnée et fixée. Pour rappel, la ligne suivante n'est exécutée qu'une seule fois au démarrage du serveur, car il s'agit d'un attribut de classe:
datetime_released = models.DateTimeField(default=timezone.now())
et donc timezone.now()
n'est exécuté qu'une seule fois. Passer un timezone.now
Appelable permet de recalculer la valeur quand elle doit l'être.
now () est exécuté lorsque le modèle est chargé et renvoie une chaîne objet/heure datetime lors du chargement. (d'où le Django!) (Le fichier modèle s'il est entièrement exécuté au démarrage du serveur)
now passera sur la méthode now et ne sera exécuté que lorsque la classe/le modèle sera instancié, créant l'horodatage au bon moment (de la bonne façon et ce que la plupart des gens essaient de réaliser).
Dans l'exemple de filtre, il n'est appelé que lorsque la fonction de filtrage est appelée. si vous n'avez pas exécuté (now ()) et alimenterez la méthode, et ne générerez jamais l'objet datetime requis. (erreur, attendu une chaîne, obtenu, autre chose)
Dans self.filter(date_available__lte = timezone.now())
, vous souhaitez effectuer une requête sur la base de données en fonction de l'heure actuelle. Vous en avez donc besoin au format chaîne.
Dans datetime_released = models.DateTimeField(default=timezone.now)
, vous voulez que l'heure par défaut soit l'heure actuelle. Vous ne pouvez donc pas y avoir de chaîne. Au lieu de cela, vous fournissez une fonction qui peut retourner l'heure actuelle.