Pour Django 1.1.
J'ai ceci dans mes models.py:
class User(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
Lors de la mise à jour d'une ligne, j'obtiens:
[Sun Nov 15 02:18:12 2009] [error] /home/ptarjan/projects/twitter-meme/django/db/backends/mysql/base.py:84: Warning: Column 'created' cannot be null
[Sun Nov 15 02:18:12 2009] [error] return self.cursor.execute(query, args)
La partie pertinente de ma base de données est:
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
Est-ce une source de préoccupation?
Question secondaire: dans mon outil d'administration, ces deux champs n'apparaissent pas. Est-ce attendu?
python
django
datetime
django-models
django-admin
Paul Tarjan
la source
la source
update()
méthode n'appellera pas,save()
ce qui signifie qu'elle n'a pas pu mettre à jour lemodified
champ automatiquementRéponses:
Tout champ avec l'
auto_now
attribut défini héritera égalementeditable=False
et n'apparaîtra donc pas dans le panneau d'administration. Il a été question dans le passé de faire disparaître les argumentsauto_now
etauto_now_add
, et bien qu'ils existent toujours, je pense que vous feriez mieux d'utiliser une méthode personnaliséesave()
.Donc, pour que cela fonctionne correctement, je vous recommande de ne pas utiliser
auto_now
ouauto_now_add
et de définir votre propresave()
méthode pour vous assurer qu'ellecreated
n'est mise à jour que si elleid
n'est pas définie (comme lorsque l'élément est créé pour la première fois), et la mettre à jour àmodified
chaque fois que l'élément est enregistré.J'ai fait exactement la même chose avec d'autres projets que j'ai écrits en utilisant Django, et ainsi vous
save()
ressembleriez à ceci:J'espère que cela t'aides!
Modifier en réponse aux commentaires:
La raison pour laquelle je reste fidèle à la surcharge par
save()
rapport à l'utilisation de ces arguments de champ est double:django.utils.timezone.now()
vs.datetime.datetime.now()
, car cela retournera undatetime.datetime
objet sensible à TZ ou naïf selonsettings.USE_TZ
.Pour savoir pourquoi le PO a vu l'erreur, je ne sais pas exactement, mais il semble que ce
created
ne soit même pas du tout peuplé, malgré le faitauto_now_add=True
. Pour moi, il s'agit d'un bug et souligne l'élément n ° 1 dans ma petite liste ci-dessus:auto_now
etauto_now_add
est au mieux feuilleté.la source
save()
sur chacun de mes modèles est beaucoup plus pénible que d'utiliser leauto_now
(car j'aime avoir ces champs sur tous mes modèles). Pourquoi ces params ne fonctionnent-ils pas?Mais je voulais souligner que l'opinion exprimée dans la réponse acceptée est quelque peu dépassée. Selon des discussions plus récentes (bogues django # 7634 et # 12785 ), auto_now et auto_now_add ne vont nulle part, et même si vous allez à la discussion d'origine , vous trouverez des arguments solides contre le RY (comme dans DRY) dans la sauvegarde personnalisée méthodes.
Une meilleure solution a été proposée (types de champs personnalisés), mais n'a pas pris suffisamment d'élan pour en faire django. Vous pouvez écrire le vôtre en trois lignes (c'est la suggestion de Jacob Kaplan-Moss ).
la source
En parlant d'une question secondaire: si vous voulez voir ces champs dans admin (bien que vous ne puissiez pas le modifier), vous pouvez ajouter
readonly_fields
à votre classe admin.Eh bien, cela ne s'applique qu'aux dernières versions de Django (je crois, 1.3 et plus)
la source
XxAdmin
classe. Je l'ai lu trop rapidement et j'ai essayé de l'ajouter à mesAdminForm
ouModelForm
classes et je ne savais pas pourquoi ils ne rendaient pas les "champs en lecture seule". BTW, est-il possible d'avoir de vrais "champs en lecture seule dans un formulaire?"Je pense que la solution la plus simple (et peut-être la plus élégante) ici est de tirer parti du fait que vous pouvez définir
default
un appelable. Donc, pour contourner la gestion spéciale par admin de auto_now, vous pouvez simplement déclarer le champ comme suit:Il est important de ne pas l'utiliser
timezone.now()
car la valeur par défaut ne serait pas mise à jour (c'est-à-dire que la valeur par défaut n'est définie que lorsque le code est chargé). Si vous vous retrouvez souvent à faire cela, vous pouvez créer un champ personnalisé. Cependant, c'est déjà assez sec, je pense.la source
makemigrations
il interprète la valeur par défaut comme l'heure à laquelle vous exécutezmakemigrations
et pense donc que la valeur par défaut a changé!default=timezone.now()
plutôt que ce qui est recommandé:default=timezine.now
(pas de parenthèses)?Si vous modifiez votre classe de modèle comme ceci:
Ensuite, ce champ apparaîtra dans ma page de changement d'administrateur
la source
python manage.py makemigrations
: KeyError: u'editable 'D'après ce que j'ai lu et mon expérience avec Django jusqu'à présent, auto_now_add est bogué. Je suis d'accord avec jthanism --- remplacer la méthode de sauvegarde normale, c'est propre et vous savez ce qui se passe. Maintenant, pour le rendre sec, créez un modèle abstrait appelé TimeStamped:
Et puis, quand vous voulez un modèle qui a ce comportement horodaté, il suffit de sous-classe:
Si vous souhaitez que les champs apparaissent dans l'administrateur, supprimez simplement l'
editable=False
optionla source
timezone.now()
utilisez-vous ici? Je supposedjango.utils.timezone.now()
, mais je ne suis pas positif. Aussi, pourquoi utilisertimezone.now()
plutôt quedatetime.datetime.now()
?timezone.now()
est qu'il est sensible au fuseau horaire, alors qu'ildatetime.datetime.now()
est naïf. Vous pouvez en lire plus ici: docs.djangoproject.com/en/dev/topics/i18n/timezonesdefault=timezone.now
dans le constructeur de champ?update_fields
arg est fourni et que 'last_modified' n'est pas dans la liste, j'ajouterais:if 'update_fields' in kwargs and 'last_modifed' not in kwargs['update_fields']: kwargs['update_fields'].append('last_modified')
Non, Django l'ajoute automatiquement pour vous lors de la sauvegarde des modèles, c'est donc normal.
Étant donné que ces champs sont ajoutés automatiquement, ils ne sont pas affichés.
Pour ajouter à ce qui précède, comme l'a dit synack, il y a eu un débat sur la liste de diffusion django pour le supprimer, car il n'est "pas bien conçu" et est "un hack".
De toute évidence, vous n'avez pas à l'écrire sur tous les modèles. Vous pouvez l'écrire sur un modèle et en hériter d'autres.
Mais, comme
auto_add
etauto_now_add
sont là, je les utiliserais plutôt que d'essayer d'écrire une méthode moi-même.la source
J'avais besoin de quelque chose de similaire aujourd'hui au travail. La valeur par défaut est
timezone.now()
, mais modifiable à la fois dans les vues d'administration et de classe héritées deFormMixin
, donc pour créé dans mon,models.py
le code suivant remplit ces conditions:Pour
DateTimeField
, je suppose que supprimer le.date()
de la fonction et changerdatetime.date
pourdatetime.datetime
ou mieuxtimezone.datetime
. Je ne l'ai pas essayé avecDateTime
, seulement avecDate
.la source
Vous pouvez utiliser
timezone.now()
pour créé etauto_now
pour modifié:Si vous utilisez une clé primaire personnalisée au lieu de la valeur par défaut
auto- increment int
,auto_now_add
cela entraînera un bogue.Voici le code de DateTimeField.pre_save par défaut de Django avec
auto_now
etauto_now_add
:Je ne sais pas quel est le paramètre
add
. J'espère que ce sera quelque chose comme:la source
Quant à votre écran Admin, voyez cette réponse .
Remarque:
auto_now
etauto_now_add
sont définiseditable=False
par défaut, c'est pourquoi cela s'applique.la source
auto_now=True
n'a pas fonctionné pour moi dans Django 1.4.1, mais le code ci-dessous m'a sauvé. C'est pour le datetime sensible au fuseau horaire.la source
Ici, nous avons créé et mis à jour des colonnes qui auront un horodatage lors de la création et lorsque quelqu'un a modifié les commentaires.
auto_now_add fixera l'heure à laquelle une instance est créée tandis que auto_now fixera l'heure à laquelle quelqu'un modifiera ses commentaires.
la source
Voici la réponse si vous utilisez le sud et que vous souhaitez définir par défaut la date à laquelle vous ajoutez le champ à la base de données:
Choisissez l'option 2 puis: datetime.datetime.now ()
Ressemble à ça:
la source