DateTimeField ne s'affiche pas dans le système d'administration

88

Pourquoi mon champ "date" n'apparaît-il pas dans le système d'administration?

Dans mon fichier admin.py j'ai

from django.contrib import admin
from glasses.players.models import *
admin.site.register(Rating)

et le modèle de notation a un champ appelé "date" qui ressemble à ceci

date = models.DateTimeField(editable=True, auto_now_add=True)

Cependant, dans le système d'administration, le champ ne s'affiche pas, même s'il editableest défini sur True.

Est-ce que quelqu'un a une idée?

toqué
la source

Réponses:

56

Je crois que la raison appartient au auto_now_addterrain.

De cette réponse :

Tout champ avec l'attribut auto_now défini héritera également de editable = False et n'apparaîtra donc pas dans le panneau d'administration.

Également mentionné dans la documentation :

Telle qu'actuellement implémentée, la définition de auto_now ou auto_now_add sur True fera que le champ aura editable = False et blank = True.

Cela a du sens, car il n'y a aucune raison de rendre le champ modifiable s'il va être écrasé par la date / heure actuelle lorsque l'objet est enregistré.

Shawn Chin
la source
31
Bien que vous devriez sûrement pouvoir modifier auto_now_addvia l'administrateur après la création de l'entrée?
Christopher Orr
68
Vous devriez également pouvoir simplement l' afficher dans l'interface d'administration, même s'il n'était pas modifiable.
Brad
1
Veuillez vous référer à la réponse de @hunger ci-dessous pour savoir comment l'afficher en tant que champ en lecture seule dans l'interface d'administration.
guival le
1
Il est judicieux d'avoir un champ modifiable si le champ n'est initialisé que lors de la création d'un objet (auto_now_add = True).
sergzach
206

Si vous voulez vraiment voir la date dans le panneau d'administration, vous pouvez ajouter readonly_fieldsdans admin.py :

class RatingAdmin(admin.ModelAdmin):
    readonly_fields = ('date',)

admin.site.register(Rating,RatingAdmin)

Tout champ que vous spécifiez sera ajouté en dernier après les champs modifiables. Pour contrôler l'ordre, vous pouvez utiliser les fieldsoptions.

Des informations supplémentaires sont disponibles dans la documentation Django .

Faim
la source
33
CECI est la vraie réponse !!
GreenAsJade
4
si vous stipulez un, fieldsvous devez également mettre votre champ dans ce champ, donc vous en auriez besoin à la fois readonly_fieldset fieldssinon le champ ne s'afficherait pas.
Bjorn
Je voulais juste noter que cela s'appliquait également si vous utilisez fieldsets, je viens de rencontrer ce problème aujourd'hui.
Kevin Brown
1
Cela fera apparaître le champ uniquement lorsque nous cliquons et ouvrons une entrée particulière. Si vous souhaitez que le champ soit visible dans la vue de liste elle-même, stackoverflow.com/a/34966908/4440874
Jyotman Singh
1
Notez que je ne sais pas pourquoi mais cela ne semble pas fonctionner pour DateTimeFields auto_now_add=Truesous Django 1.9. Une (sorte de) solution de contournement consiste à les ajouter au list_displaytuple à la place. Edit: Cela fonctionnera si vous ajoutez également votre champ fieldscomme @BjornTipling mentionné.
Taylor Edmiston le
23

Piratage majeur:

Si vous avez vraiment besoin de faire cela (comme je le fais), vous pouvez toujours le contourner en définissant immédiatement le champ pour être "modifiable" en définissant le champ comme suit:

class Point(models.Model):
  mystamp=models.DateTimeField("When Created",auto_now_add=True)
  mystamp.editable=True

Cela rendra le champ modifiable, vous pouvez donc le modifier. Cela semble fonctionner correctement, du moins avec le moteur de sauvegarde mysql. Je ne peux pas dire pour certian si d'autres magasins de support rendraient ces données immuables dans la base de données et causeraient ainsi un problème lors d'une tentative d'édition, alors utilisez-les avec prudence .

Brad
la source
Non, ne fais pas ça, utilise la solution readonly_fields décrite par Hunger.
GreenAsJade
2
@GreenAsJade: Une justification serait bien.
mhsmith le
@mhsmith Raison pour utiliser la solution de Hunger au lieu de ceci: parce que c'est un hack majeur et qu'il est livré avec "utiliser avec prudence", alors que la solution de Hunger utilise django de la manière dont il est conçu pour être utilisé. Pourquoi risqueriez-vous un piratage majeur alors que vous pouvez faire ce dont vous avez besoin de manière légitime et soutenue?
GreenAsJade
6
Cette solution de piratage n'est pas si mauvaise. Le seul cas d'utilisation que je vois est le test - lorsque le testeur doit modifier la date.
jacoor
2
juste un avertissement: ce hack a gâché les migrations pour moi
damio
16

En fonction de vos besoins spécifiques et des nuances de différence de comportement, vous pouvez procéder comme suit:

from django.utils.timezone import now

class MyModel(models.Model):
    date = models.DateTimeField(default=now)

Le champ par défaut peut être utilisé de cette façon: https://docs.djangoproject.com/en/dev/ref/models/fields/#default

The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is created.

Cela ne définit pas modifiable sur False

orblivion
la source
1
J'utiliserais à la from django.utils.timezone import nowplace de datetime.now, mais cela semble prometteur.
amjoconn
Merci, je l'ai changé.
orblivion
Stackoverflow est génial car certaines réponses vous font réaliser que vous n'avez pas posé la bonne question! Merci.
Samuel Dauzon
5

Cela pourrait avoir à voir avec le fait que auto_now_add est vrai. Peut-être qu'au lieu de ce paramètre pour capturer la date lors de l'ajout, vous pouvez remplacer la méthode de sauvegarde du modèle pour insérer la date-heure lorsque l'id est nul.

class Rating(models.Model):

    ....
    def save(self, *args, **kwargs)
        if not self.id: 
            self.date = datetime.datetime.now()
Joe J
la source
Si vous l'avez fait, il n'y a aucune raison de définir le champ comme auto_now
FallenAngel
Je ne sais pas pourquoi le vote négatif; le premier lien fourni par Shawn Chin indique une approche similaire.
Joe J
C'est une alternative judicieuse, en supposant qu'elle auto_nown'est pas utilisée et editable=False. +1
Shawn Chin
3

Si vous souhaitez qu'un champ soit visible dans la liste de toutes vos entrées (lorsque vous cliquez sur un modèle dans les administrateurs) et non lorsque vous ouvrez cette entrée particulière, alors -

class RatingAdmin(admin.ModelAdmin):
    list_display = ('name', 'date') 

admin.site.register(Rating, RatingAdmin)

«nom» étant votre champ principal ou tout autre champ que vous souhaitez afficher dans le panneau d'administration.

De cette façon, vous pouvez spécifier toutes les colonnes que vous souhaitez voir.

Jyotman Singh
la source
0

Vous ne pouvez pas faire ça, consultez la documentation

auto_now et auto_now_add sont tous des champs non modifiables et vous ne pouvez pas les remplacer ...

Ange déchu
la source