347 votes

Auto_now_add et auto_now de Django

Pour Django 1.1.

J’ai ceci dans mon models.py :

Pour mettre à jour une ligne, j’obtiens :

la partie pertinente de ma db est :

Est cette cause d’inquiétude ?

Question côté : dans mon admin tool, ces 2 champs ne s’affichent pas. Qu’attend-on ?

462voto

jathanism Points 15208

N'importe quel champ avec l' auto_now ensemble d'attributs sera également hériter editable=False et, par conséquent, ne sera pas affiché dans le panneau d'admin. Il a déjà été question dans le passé à propos de faire de l' auto_now et auto_now_add arguments de s'en aller, et bien qu'ils existent encore, je pense que vous êtes mieux simplement en utilisant une coutume save() méthode.

Donc, pour faire ce travail correctement, je vous recommande de ne pas utiliser auto_now ou auto_now_add et au lieu de définir votre propre save() méthode pour vous assurer que created est mise à jour uniquement si id n'est pas définie (comme lorsque l'élément est créé en premier), et de la mise à jour de modified chaque fois que l'élément est enregistré.

J'ai fait exactement la même chose avec les autres projets que j'ai écrite à l'aide de Django, et votre save() ressemblerait à ceci:

import datetime

class User(models.Model):
    created     = models.DateTimeField(editable=False)
    modified    = models.DateTimeField()

    def save(self, *args, **kwargs):
        ''' On save, update timestamps '''
        if not self.id:
            self.created = datetime.datetime.today()
        self.modified = datetime.datetime.today()
        return super(User, self).save(*args, **kwargs)

Espérons que cette aide!

Edit en réponse aux commentaires:

La raison pour laquelle je viens de coller avec la surcharge save() vs en s'appuyant sur ces arguments sont de deux ordres:

  1. Ladite hauts et des bas avec leur fiabilité. Ces arguments sont fortement tributaire de la façon dont chaque type de base de données de Django sait comment interagir avec des friandises un timbre de date/heure de champ, et semble se briser et/ou de changer entre chaque version. (Je crois que c'est l'élan derrière l'appel de les avoir supprimés).
  2. Le fait qu'ils ne fonctionnent que sur DateField, DateTimeField, et TimeField, et en utilisant cette technique, vous êtes en mesure de remplir automatiquement tout type de champ à chaque fois qu'un élément est enregistré.

Pour remédier à cela, l'OP a vu l'erreur, je ne sais pas exactement, mais il ressemble created n'est même pas remplie, malgré auto_now_add=True. Pour moi, il se distingue comme un bug, et souligne l'élément n ° 1 dans mon petit liste ci-dessus: auto_now et auto_now_add sont feuilletée au mieux.

221voto

Shai Berger Points 872

Bah... Pas assez de réputation pour le commentaire... Mais je voulais souligner que l'opinion exprimée dans l'acceptation réponse est quelque peu obsolète. Selon les plus récentes discussions (django bugs #7634 et #12785), auto_now et auto_now_add ne vont pas n'importe où, et même si vous allez à la discussion initiale, vous aurez à trouver des arguments solides contre le RY (en SEC) dans des méthodes enregistrer.

Une meilleure solution a été offert (types de champs personnalisés), mais ne gagnent pas assez d'élan pour faire de django. Vous pouvez écrire votre propre en trois lignes (c'est Jacob Kaplan-Moss suggestion).

class AutoDateTimeField(models.DateTimeField):
    def pre_save(self, model_instance, add):
        return datetime.datetime.now()

#usage
created_at = models.DateField(default=timezone.now)
updated_at = models.AutoDateTimeField(default=timezone.now)

44voto

DataGreed Points 1675

Parler d'une question secondaire: si vous souhaitez voir ces champs dans admin (vous ne pourrez pas le modifier), vous pouvez ajouter readonly_fields à votre classe admin.

 class SomeAdmin(ModelAdmin):
    readonly_fields = ("created","modified",)
 

Eh bien, cela s'applique uniquement aux dernières versions de Django (je crois, version 1.3 et supérieure)

38voto

Josh Points 2820

Je pense que le plus simple (et peut-être le plus élégant) solution ici est d'exploiter le fait que vous pouvez configurer default pour un appelable. Donc, pour contourner les admin du traitement spécial des auto_now, vous pouvez simplement déclarer le domaine de la sorte:

from django.utils import timezone
date_filed = models.DateField(default=timezone.now)

Il est important que vous n'utilisez pas l' timezone.now() comme valeur par défaut ne serait pas de mise à jour (c'est à dire, la valeur par défaut est défini uniquement lorsque le code est chargé). Si vous vous retrouver à faire beaucoup, vous pouvez créer un champ personnalisé. Cependant, c'est assez SEC, déjà je pense.

19voto

Eric Zheng Points 41

J'ai trouvé une solution

si j'ai une classe de modèle comme:

 class MyModel(models.Model):
    time = models.DatetimeField(auto_now_add=True)
    time.editable = True
 

Ensuite, ce champ apparaîtra dans ma page d'administration

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X