Автоматическая дата создания для объектов формы модели Django?

153

Каков наилучший способ автоматически установить дату создания объекта, а также поле, которое будет записывать время последнего обновления объекта?

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')

Я получаю ошибку:

objects_object.created_at may not be NULL

Нужно ли вручную устанавливать это значение? Я думал, что это точка параметров, передаваемых DateTimeField(или они являются просто значениями по умолчанию, и, поскольку я установил, editable=Falseони не отображаются в форме, следовательно, не отправляются в запросе и, следовательно, не получают положить в форму?).

Какой лучший способ сделать это? __init__Метод?

Роджер
источник

Ответы:

313

Вы можете использовать параметры auto_nowи auto_now_addдля updated_atи created_atсоответственно.

class MyModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
Маной Говиндан
источник
31
auto_nowи auto_now_addсчитаются злом, поэтому старайтесь избегать их. Этот ответ объясняет почему и обеспечивает лучший подход, переопределяя save()метод.
Грегольцов
3
он выдает эту ошибку: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
удалите строки в базах данных или отметьте опцию 1 и добавьте timezone.now ()
mullerivan
1
Я думаю, что комментарий @ gregoltsov устарел на данный момент. Использование auto_now_addили auto_nowработает просто отлично. Он устанавливает поле перед сохранением модели ( github.com/django/django/blob/stable/3.0.x/django/db/models/… ).
yndolok
26

Что ж, приведенный выше ответ правильный, auto_now_add и auto_now сделали бы это, но было бы лучше создать абстрактный класс и использовать его в любой модели, где вам нужны поля created_atи updated_atполя.

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

    class Meta:
        abstract = True

Теперь, где бы вы ни захотели его использовать, вы можете делать простое наследование, и вы можете использовать метку времени в любой модели, которую вам нравится.

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

Таким образом, вы можете использовать объектно-ориентированное повторное использование в Django DRY (не повторяйтесь)

Читранк Диксит
источник