Как моя модель django DateField может добавить 30 дней к предоставленному значению? - PullRequest
20 голосов
/ 04 февраля 2010

, как следует из названия.Я хочу добавить 30 дней в поле DateField.Это автоматически заполняется при создании записи с использованием auto_now_add=True

Есть идеи, как это сделать?

Спасибо

Ответы [ 5 ]

51 голосов
/ 08 марта 2013

Нет необходимости реализовывать пользовательский метод сохранения.

Также делать это default=datetime.now()+timedelta(days=30) абсолютно неправильно!Он оценивается, когда вы запускаете свой экземпляр django.Если вы используете apache, он, вероятно, будет работать, потому что в некоторых конфигурациях apache отзывает ваше приложение django при каждом запросе, но, тем не менее, вы когда-нибудь сможете найти себя, просматривая код и пытаясь понять, почему это вычисляется не так, как вы ожидаете.

Правильный способ сделать это - передать вызываемый объект в аргумент по умолчанию.Это может быть функция datetime.today или ваша пользовательская функция.Затем он оценивается каждый раз, когда вы запрашиваете новое значение по умолчанию.

def get_deadline():
    return datetime.today() + timedelta(days=20)

class Bill(models.Model):
    name = models.CharField(max_length=50)
    customer = models.ForeignKey(User, related_name='bills')
    date = models.DateField(default=datetime.today)
    deadline = models.DateField(default=get_deadline)
33 голосов
/ 04 февраля 2010

// Обновление

Комментарий под оригинальным постом заставил меня задуматься. Я думаю, что это лучшее решение на данный момент:

from datetime import datetime, timedelta

class MyModel(models.Model):
   mydate = models.DateTimeField(default=datetime.now()+timedelta(days=30))

// 2. Обновление

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

Решение:

class MyModel(models.Model):
  mydate = models.DateTimeField(editable=False)
  daysadded = models.IntegerField()

  def save(self):
    from datetime import datetime, timedelta
    d = timedelta(days=self.daysadded)

    if not self.id:
      self.mydate = datetime.now() + d
      super(MyModel, self).save()

Как уже упоминалось в Guru, вы должны переопределить метод сохранения ваших моделей.

* * Пример тысячи двадцать-одина: * ** 1023 тысячу двадцать две *

class MyModel(models.Model):
  mydate = models.DateTimeField(auto_now_add=True)      

  def save(self):
    from datetime import timedelta
    d = timedelta(days=30)

    // only add 30 days if it's the first time the model is saved
    if not self.id:
      // not saving the model before adding the timedelta gave me errors 
      super(MyModel, self).save()

      self.mydate += d

      // final save
      super(MyModel, self).save()

Это не лучший способ для меня, так как вы должны сохранить модель дважды. Но использование auto_now_add требует от вас сохранения модели перед созданием экземпляра datetime для mydate.

Другой подход, который требует только одного сохранения:

class MyModel(models.Model):
  mydate = models.DateTimeField(editable=False) // editable=False to hide in admin

  def save(self):
    from datetime import datetime, timedelta
    d = timedelta(days=30)

    // only add 30 days if it's the first time the model is saved
    if not self.id:
      self.mydate = datetime.now() + d
      super(MyModel, self).save()

Надеюсь, это помогло!

3 голосов
/ 04 февраля 2010

Используйте Питонов timedelta:

from datetime import timedelta
d = timedelta(days=30)

# object is your current instance of the model
object.yourdatefield += d
# or this because I am not sure whether the previous works
object.yourdatefield = object.yourdatefield + d

object.save()

А из документации Django :

DateField
Дата, представленная в Python экземпляром datetime.date.

Если вы хотите добавить 30 дней на создание объекта, забудьте о auto_now_add=True и сделайте так, как предлагает Гуру. Информацию о переопределении save() можно также найти в документации Django .

1 голос
/ 04 февраля 2010

Отменить сохранение в модели и во время сохранения проверить, заполнен ли pk.

>>> from datetime import datetime
>>> from datetime import timedelta
>>> cur_date = datetime.now()
>>> cur_date
datetime.datetime(2010, 2, 4, 5, 0, 24, 437405)
>>> cur_date+timedelta(days=30)
datetime.datetime(2010, 3, 6, 5, 0, 24, 437405)
0 голосов
/ 09 февраля 2017

документ для timedelta: https://docs.python.org/2/library/datetime.html

def make_timedelta(seconds):
        return timedelta(days=seconds // 86399, seconds=seconds % 86399)
...