Automatyczna data utworzenia obiektów formularza modelu Django?

153

Jaki jest najlepszy sposób na automatyczne ustawienie daty utworzenia obiektu, a także pola, które będzie rejestrować, kiedy obiekt był ostatnio aktualizowany?

models.py:

created_at = models.DateTimeField(False, True, editable=False)
updated_at = models.DateTimeField(True, True, editable=False)

views.py:

if request.method == 'POST':
    form = MyForm(request.POST)
    if form.is_valid():
        obj = form.save(commit=False)
        obj.user = request.user
        obj.save()
        return HttpResponseRedirect('obj_list')

Wyskakuje mi błąd:

objects_object.created_at may not be NULL

Czy muszę samodzielnie ustawić tę wartość ręcznie? Myślałem, że to był punkt przekazywania parametrów do DateTimeField(czy są to tylko wartości domyślne, a ponieważ ustawiłem, editable=Falseże nie są wyświetlane w formularzu, dlatego nie są przesyłane w żądaniu i dlatego nie są umieścić w formularzu?).

Jaki jest najlepszy sposób na zrobienie tego? __init__Metoda?

zrozumiałem
źródło

Odpowiedzi:

312

Można użyć auto_nowi auto_now_addopcje updated_ati created_atodpowiednio.

class MyModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
Manoj Govindan
źródło
31
auto_nowi auto_now_addsą uważane za złe, więc staraj się ich unikać. Ta odpowiedź wyjaśnia, dlaczego i zapewnia lepsze podejście, zastępując save()metodę.
gregoltsov
3
generuje ten błąd:You are trying to add a non-nullable field 'created_at' to gameuser without a default; we can't do that (the database needs something to populate existing rows). Please select a fix: 1) Provide a one-off default now (will be set on all existing rows) 2) Quit, and let me add a default in models.py Select an option: 1 Please enter the default value now, as valid Python The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now() >>> timezone.now()
Kaleem Ullah
1
usuń wiersze z baz danych lub zaznacz opcję 1 i dodaj timezone.now ()
mullerivan
1
Myślę, że komentarz @ gregoltsov jest w tym momencie nieaktualny. Używanie auto_now_addlub auto_nowdziała dobrze. Ustawia pole przed zapisaniem modelu ( github.com/django/django/blob/stable/3.0.x/django/db/models/ ... ).
yndolok
26

Cóż, powyższa odpowiedź jest poprawna, zrobiłyby to auto_now_add i auto_now , ale lepiej byłoby utworzyć klasę abstrakcyjną i użyć jej w dowolnym modelu, w którym potrzebujesz created_ati updated_atpól.

class TimeStampMixin(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

Teraz gdziekolwiek chcesz go użyć, możesz zrobić proste dziedziczenie i możesz użyć znacznika czasu w dowolnym modelu, który stworzysz.

class Posts(TimeStampMixin):
    name = models.CharField(max_length=50)
    ...
    ...

W ten sposób możesz wykorzystać zorientowaną obiektowo możliwość ponownego użycia w Django DRY (nie powtarzaj tego)

Chitrank Dixit
źródło