Für Django 1.1.
Ich habe dies in meinen models.py:
class User(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
Beim Aktualisieren einer Zeile erhalte ich:
[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)
Der relevante Teil meiner Datenbank ist:
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
Gibt dies Anlass zur Sorge?
Nebenfrage: In meinem Admin-Tool werden diese beiden Felder nicht angezeigt. Wird das erwartet?
python
django
datetime
django-models
django-admin
Paul Tarjan
quelle
quelle
update()
Methode wird nicht aufgerufen,save()
was bedeutet, dass dasmodified
Feld nicht automatisch aktualisiert werden konnteAntworten:
Jedes Feld mit dem
auto_now
Attributsatz erbt ebenfallseditable=False
und wird daher nicht im Admin-Bereich angezeigt. Es hat in der Vergangenheit die Rede gewesen über die Herstellungauto_now
undauto_now_add
Argumente gehen weg, und obwohl sie noch existieren, fühle ich Sie besser dran , nur unter Verwendung eines kundenspezifischensave()
Verfahren .Damit dies ordnungsgemäß funktioniert, würde ich empfehlen, keine
auto_now
oder zu verwendenauto_now_add
und stattdessen Ihre eigenesave()
Methode zu definieren , um sicherzustellen, dass diesecreated
nur aktualisiert wird, wenn sieid
nicht festgelegt ist (z. B. wenn das Element zum ersten Mal erstellt wird), und siemodified
jedes Mal aktualisieren zu lassen, wenn das Element erstellt wird ist gespeichert.Ich habe genau das Gleiche mit anderen Projekten gemacht, die ich mit Django geschrieben habe, und so
save()
würde Ihr aussehen:Hoffe das hilft!
Als Antwort auf Kommentare bearbeiten:
Der Grund, warum ich mich nur an Überladung
save()
halte und mich nicht auf diese Feldargumente verlasse, ist zweierlei:django.utils.timezone.now()
vs.datetime.datetime.now()
, dadatetime.datetime
abhängig davon ein TZ-fähiges oder naives Objekt zurückgegeben wirdsettings.USE_TZ
.Um zu klären, warum das OP den Fehler gesehen hat, weiß ich nicht genau, aber es sieht so aus, als wäre
created
es überhaupt nicht besetztauto_now_add=True
. Für mich ist es ein Fehler und unterstreicht Punkt 1 in meiner kleinen Liste oben:auto_now
undauto_now_add
sind bestenfalls schuppig.quelle
save()
für jedes meiner Modelle ist viel schmerzhafter als das Verwenden vonauto_now
(da ich diese Felder gerne für alle meine Modelle habe). Warum funktionieren diese Parameter nicht?Ich wollte jedoch darauf hinweisen, dass die in der akzeptierten Antwort geäußerte Meinung etwas veraltet ist. Laut neueren Diskussionen (Django-Fehler # 7634 und # 12785 ) gehen auto_now und auto_now_add nirgendwo hin, und selbst wenn Sie zur ursprünglichen Diskussion gehen , finden Sie beim benutzerdefinierten Speichern starke Argumente gegen den RY (wie in DRY) Methoden.
Es wurde eine bessere Lösung angeboten (benutzerdefinierte Feldtypen), die jedoch nicht genügend Schwung erhielt, um es in Django zu schaffen. Sie können Ihre eigenen in drei Zeilen schreiben (es ist der Vorschlag von Jacob Kaplan-Moss ).
quelle
Apropos Nebenfrage: Wenn Sie diese Felder in admin sehen möchten (Sie können sie jedoch nicht bearbeiten), können Sie
readonly_fields
sie Ihrer admin-Klasse hinzufügen .Nun, dies gilt nur für die neuesten Django-Versionen (ich glaube, 1.3 und höher)
quelle
XxAdmin
Klasse hinzugefügt werden . Ich habe es zu schnell gelesen und versucht, es meinerAdminForm
oder meinenModelForm
Klassen hinzuzufügen, und hatte keine Ahnung, warum sie die "schreibgeschützten Felder" nicht renderten. Übrigens, gibt es eine Möglichkeit, echte "Nur-Lese-Felder" in einer Form zu haben?Ich denke, die einfachste (und vielleicht eleganteste) Lösung besteht darin, die Tatsache zu nutzen, dass Sie
default
einen Callable einstellen können . Um die spezielle Behandlung von auto_now durch den Administrator zu umgehen, können Sie das Feld einfach wie folgt deklarieren:Es ist wichtig, dass Sie nicht verwenden,
timezone.now()
da der Standardwert nicht aktualisiert wird (dh der Standardwert wird nur festgelegt, wenn der Code geladen wird). Wenn Sie dies häufig tun, können Sie ein benutzerdefiniertes Feld erstellen. Dies ist jedoch schon ziemlich trocken, denke ich.quelle
makemigrations
wenn Sie es ausführenmakemigrations
, interpretiert es den Standard als den Zeitpunkt, zu dem Sie es ausführen , und denkt daher, dass sich der Standardwert geändert hat!default=timezone.now()
sondern was empfohlen wird:default=timezine.now
(keine Klammern)?Wenn Sie Ihre Modellklasse folgendermaßen ändern:
Dann wird dieses Feld auf meiner Admin-Änderungsseite angezeigt
quelle
python manage.py makemigrations
: KeyError: u'editable 'Basierend auf dem, was ich gelesen habe und meiner bisherigen Erfahrung mit Django ist auto_now_add fehlerhaft. Ich bin mit jthanism einverstanden - überschreibe die normale Speichermethode, sie ist sauber und du weißt, was passiert. Erstellen Sie zum Trocknen ein abstraktes Modell mit dem Namen TimeStamped:
Und wenn Sie ein Modell mit diesem zeitstempeligen Verhalten wünschen, gehen Sie einfach in die Unterklasse:
Wenn die Felder in admin angezeigt werden sollen, entfernen Sie einfach die
editable=False
Optionquelle
timezone.now()
du hier? Ich nehme andjango.utils.timezone.now()
, aber ich bin nicht positiv. Warum auchtimezone.now()
lieber verwenden alsdatetime.datetime.now()
?timezone.now()
ist, dass es zeitzonenbewusst ist, währenddatetime.datetime.now()
es zeitzonennaiv ist. Sie können darüber hier lesen: docs.djangoproject.com/de/dev/topics/i18n/timezonesdefault=timezone.now
Feldkonstruktors gewählt?update_fields
arg angegeben ist und 'last_modified' nicht in der Liste enthalten ist, würde ich hinzufügen:if 'update_fields' in kwargs and 'last_modifed' not in kwargs['update_fields']: kwargs['update_fields'].append('last_modified')
Nein, Django fügt es automatisch für Sie hinzu, während Sie die Modelle speichern. Es wird also erwartet.
Da diese Felder automatisch hinzugefügt werden, werden sie nicht angezeigt.
Wie Synack sagte, gab es eine Debatte über die Django-Mailingliste, um dies zu entfernen, da sie "nicht gut gestaltet" und "ein Hack" ist.
Natürlich müssen Sie es nicht auf jedes Modell schreiben. Sie können es in ein Modell schreiben und andere davon erben.
Aber, wie
auto_add
undauto_now_add
es gibt, würde ich sie verwendet anstatt zu versuchen , eine Methode selbst zu schreiben.quelle
Ich brauchte heute bei der Arbeit etwas Ähnliches. Der Standardwert muss sein
timezone.now()
, kann jedoch sowohl in Administrator- als auch in Klassenansichten bearbeitet werden , die von erben. DaherFormMixin
hat der in meinemmodels.py
Code erstellte folgende Code diese Anforderungen erfüllt:Denn
DateTimeField
ich denke, entfernen Sie die.date()
aus der Funktion und wechseln Siedatetime.date
zudatetime.datetime
oder bessertimezone.datetime
. Ich habe es nicht mit versuchtDateTime
, nur mitDate
.quelle
Sie können
timezone.now()
zum Erstellen undauto_now
Ändern verwenden:Wenn Sie anstelle des Standardschlüssels einen benutzerdefinierten Primärschlüssel verwenden
auto- increment int
,auto_now_add
führt dies zu einem Fehler.Hier ist der Code von Djangos Standard DateTimeField.pre_save mit
auto_now
undauto_now_add
:Ich bin nicht sicher, was der Parameter
add
ist. Ich hoffe es wird so etwas wie:quelle
Informationen zu Ihrer Admin-Anzeige finden Sie in dieser Antwort .
Hinweis:
auto_now
undauto_now_add
sindeditable=False
standardmäßig eingestellt, weshalb dies gilt.quelle
auto_now=True
hat in Django 1.4.1 nicht für mich funktioniert, aber der folgende Code hat mich gerettet. Es ist für zeitzonenbewusste datetime.quelle
Hier haben wir Spalten erstellt und aktualisiert, die beim Erstellen und beim Ändern des Feedbacks einen Zeitstempel haben.
auto_now_add legt die Zeit fest, zu der eine Instanz erstellt wird, während auto_now die Zeit festlegt , zu der jemand sein Feedback geändert hat.
quelle
Hier ist die Antwort, wenn Sie South verwenden und standardmäßig das Datum festlegen möchten, an dem Sie das Feld zur Datenbank hinzufügen:
Wählen Sie Option 2 und dann: datetime.datetime.now ()
Sieht aus wie das:
quelle