Django - автоматически обновлять дату после изменения стоимости

В следующей модели django:

class MyModel(models.Model):
    published = models.BooleanField(default=False)
    pub_date = models.DateTimeField('date published')

Я хочу, чтобы поле pub_date автоматически обновлялось с текущей датой, каждый раз, когда опубликованное поле изменяется на True.

Каков умный способ?

Спасибо.

Ответ 1

Все ответы были полезны, но я, наконец, сделал это так:

def save(self, *args, **kwargs):
    if self.published and self.pub_date is None:
        self.pub_date = timezone.now()
    elif not self.published and self.pub_date is not None:
        self.pub_date = None
    super(Model, self).save(*args, **kwargs)

Ответ 2

Если вы устанавливаете объект как опубликованный в администраторе Django, хороший способ сделать это - переопределить метод save_model класса вашей модели администратора.

from datetime import datetime

from django.contrib import admin


class MyModelAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        if obj.published and 'published' in form.changed_data
            obj.pub_date = datetime.now()
            obj.save()

admin.site.register(MyModel, MyModelAdmin)

Если вы устанавливаете флаг публикации в другом месте, вы можете переопределить метод save() или использовать сигнал pre_save. Это не так элегантно, потому что сложнее сказать, изменился ли флаг published. Я думаю, что вам нужно повторно извлечь объект из базы данных, чтобы проверить.

Ответ 3

следующее только изменяет вашу pub_date, если опубликовано было изменено с False на True:

from datetime import datetime

def __init__(self, *args, **kwargs):
    super(MyModel, self).__init__(*args, **kwargs)
    self.old_published = self.published

def save(self, *args, **kwargs):
    if self.published and self.old_published != self.published:
        self.pub_date = datetime.now()
    super(Model, self).save(*args, **kwargs)

Ответ 4

Вы хотите добавить поле auto_now и установить его в True. Это будет обновляться с текущей отметкой времени при каждом обновлении модели.

pub_date = models.DateTimeField('date_published', auto_now=True)

Вы можете прочитать об этом здесь


.Изменить

Извините, что вы действительно хотите изменить метку времени, когда значение опубликованного установлено в True. Действительно простой способ сделать это - получить исходное значение модели, а затем переопределить метод save, чтобы он обновлялся, когда для него установлено значение True. Вот что вы добавляете в свой код:

class MyModel(models.Model):
    published = models.BooleanField(default=False)
    pub_date = models.DateTimeField('date published')

    def __init__(self, *args, **kwargs):
        super(MyModel, self).__init__(*args, **kwargs)
        self._published = self.published

    def save(self, *args, **kwargs):
        if not self._published and self.published:
            self.pub_date = django.timezone.now()
        super(MyModel, self).save(*args, **kwargs)

Ответ 5

Создайте метод publish():

def publish(self):
    self.published = True
    self.pub_date = datetime.datetime.now()
    self.save()

Ответ 6

просто переопределить метод обновления

from django.utils import timezone


class Vehicle(models.Model):

    class Meta:
        ordering = ['-created']

    created = models.DateTimeField(default=timezone.now)
    updated = models.DateTimeField(default=timezone.now)

    def update(self, *args, **kwargs):
        kwargs.update({'updated': timezone.now})
        super().update(*args, **kwargs)

        return self