DateTimeField non viene visualizzato nel sistema di amministrazione


90

Come mai il mio campo "data" non compare nel sistema di amministrazione?

Nel mio file admin.py ho

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

e il modello di valutazione ha un campo chiamato "data" che assomiglia a questo

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

Tuttavia, all'interno del sistema di amministrazione, il campo non viene visualizzato, anche se editableè impostato su True.

Qualcuno ha qualche idea?

Risposte:


59

Credo che la ragione stia nel auto_now_addcampo.

Da questa risposta :

Qualsiasi campo con l'attributo auto_now impostato erediterà anche editable = False e quindi non verrà visualizzato nel pannello di amministrazione.

Menzionato anche nei documenti :

Come attualmente implementato, l'impostazione di auto_now o auto_now_add su True farà sì che il campo abbia modificabile = False e vuoto = True impostato.

Questo ha senso, dal momento che non c'è motivo per avere il campo modificabile se verrà sovrascritto con il datetime corrente quando l'oggetto viene salvato.


31
Anche se sicuramente dovresti essere in grado di modificare auto_now_addtramite l'amministratore dopo che la voce è stata creata per la prima volta?
Christopher Orr

70
Dovresti anche essere in grado di visualizzarlo semplicemente nell'interfaccia di amministrazione, anche se non era modificabile.
Brad

1
Fare riferimento alla risposta di @hunger di seguito per come visualizzarlo come campo di sola lettura nell'interfaccia di amministrazione.
Guival

1
Ha senso avere un campo modificabile se il campo viene avviato solo alla creazione di un oggetto (auto_now_add = True).
sergzach

210

Se davvero si vuole vedere la data nel pannello di amministrazione, è possibile aggiungere readonly_fieldsin admin.py :

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

admin.site.register(Rating,RatingAdmin)

Qualsiasi campo specificato verrà aggiunto per ultimo dopo i campi modificabili. Per controllare l'ordine puoi utilizzare le fieldsopzioni.

Ulteriori informazioni sono disponibili nei documenti Django .


33
QUESTA è la vera risposta !!
GreenAsJade

4
se imposti un fieldsdevi anche mettere il tuo campo in quello, quindi ne avresti bisogno sia dentro readonly_fieldsche fieldsaltrimenti il ​​campo non si presenterebbe.
Bjorn

Volevo solo notare che questo vale anche se stai usando fieldsets, ho appena incontrato questo problema oggi.
Kevin Brown

1
Questo farà apparire il campo solo quando clicchiamo e apriamo una determinata voce. Se si desidera che il campo sia visibile nella listview sé poi stackoverflow.com/a/34966908/4440874
Jyotman Singh

1
Nota che non sono sicuro del perché, ma questo non sembra funzionare per DateTimeFields con auto_now_add=TrueDjango 1.9. Una (sorta di) soluzione alternativa è aggiungerli list_displayinvece alla tupla. Modifica: funzionerà se aggiungi anche il tuo campo fieldscome menzionato da @BjornTipling.
Taylor Edmiston

23

Hack principale:

Se hai davvero bisogno di fare questo (come me) puoi sempre aggirarlo impostando immediatamente il campo in modo che sia "modificabile" definendolo come segue:

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

Questo renderà il campo modificabile, quindi puoi effettivamente modificarlo. Sembra funzionare bene, almeno con il motore di supporto mysql. Non posso dire per certian se altri archivi di supporto renderebbero questi dati immutabili nel database e quindi causerebbero un problema quando si tenta di modificare, quindi usalo con cautela .


Nah, non farlo, usa la soluzione readonly_fields descritta da Hunger.
GreenAsJade

2
@GreenAsJade: una logica sarebbe carina.
mhsmith

@mhsmith Razionale per usare la soluzione di Hunger invece di questa: perché questo è un grosso trucco e viene fornito con "usalo con cautela", mentre la soluzione di Hunger usa django nel modo in cui è stato progettato per essere utilizzato. Perché rischieresti un grosso hack quando puoi fare ciò di cui hai bisogno in modo legittimo e supportato?
GreenAsJade

6
Questa soluzione di hacking non è poi così male. L'unico caso d'uso per questo, tuttavia, vedo è il test, quando il tester deve modificare la data.
jacoor

2
solo un avvertimento: questo hack ha incasinato le migrazioni per me
damio

16

A seconda delle tue esigenze specifiche e di eventuali sfumature nella differenza di comportamento, potresti fare quanto segue:

from django.utils.timezone import now

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

Il campo predefinito può essere utilizzato in questo modo: 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.

Questo non imposta modificabile su False


1
Lo userei al from django.utils.timezone import nowposto di datetime.now, ma sembra promettente.
amjoconn

Grazie, l'ho cambiato.
orblivion

Stackoverflow è fantastico perché, alcune risposte ti fanno capire che non hai fatto la domanda giusta! Grazie.
Samuel Dauzon

5

Potrebbe avere a che fare con il fatto che auto_now_add sia vero. Forse invece di quel parametro per catturare la data in aggiunta, potresti sovrascrivere il metodo di salvataggio del modello per inserire il datetime quando l'id è nullo.

class Rating(models.Model):

    ....
    def save(self, *args, **kwargs)
        if not self.id: 
            self.date = datetime.datetime.now()

Se lo hai fatto, non c'è motivo di definire il campo come auto_now
FallenAngel

Non sono sicuro del motivo per cui il voto negativo; il primo collegamento fornito da Shawn Chin indica un approccio simile.
Joe J

Questa è un'alternativa sensata, supponendo che auto_nownon sia utilizzato e editable=False. +1
Shawn Chin

3

Se vuoi che un campo sia visibile nell'elenco di tutte le tue voci (quando fai clic su un modello nelle persone dell'amministratore) e non quando apri quella particolare voce, allora:

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

admin.site.register(Rating, RatingAdmin)

"nome" è il tuo campo principale o qualsiasi altro campo che desideri visualizzare nel pannello di amministrazione.

In questo modo puoi specificare tutte le colonne che vuoi vedere.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.