ИЗМЕНЕНО:
Как я могу установить в поле Django значение по умолчанию для функции, которая оценивается каждый раз, когда создается новый объект модели?
Я хочу сделать что-то вроде следующего, за исключением того, что в этом коде код оценивается один раз и устанавливает по умолчанию ту же дату для каждого созданного объекта модели, а не оценивает код каждый раз, когда создается объект модели:
from datetime import datetime, timedelta
class MyModel(models.Model):
# default to 1 day from now
my_date = models.DateTimeField(default=datetime.now() + timedelta(days=1))
ОРИГИНАЛ:
Я хочу создать значение по умолчанию для параметра функции, чтобы он был динамическим и вызывался и устанавливался каждый раз при вызове функции. Как я могу это сделать? например,
from datetime import datetime
def mydate(date=datetime.now()):
print date
mydate()
mydate() # prints the same thing as the previous call; but I want it to be a newer value
В частности, я хочу сделать это в Django, например,
from datetime import datetime, timedelta
class MyModel(models.Model):
# default to 1 day from now
my_date = models.DateTimeField(default=datetime.now() + timedelta(days=1))
django
django-models
parameters
lambda
default
Роб Беднарк
источник
источник
Ответы:
Вопрос неверный. При создании поля модели в Django вы не определяете функцию, поэтому значения функции по умолчанию не имеют значения:
Эта последняя строка не определяет функцию; он вызывает функцию для создания поля в классе.
PRE Django 1.7
Django позволяет передавать вызываемый объект по умолчанию , и он будет вызывать его каждый раз, как вы хотите:
Django 1.7+
Обратите внимание, что начиная с Django 1.7 использование лямбда в качестве значения по умолчанию не рекомендуется (см. Комментарий @stvnw). Правильный способ сделать это - объявить функцию перед полем и использовать ее как вызываемый объект в default_value с именем arg:
Подробнее в ответе @simanas ниже
источник
get_default_my_date
?Делая это
default=datetime.now()+timedelta(days=1)
совершенно неправильно!Он оценивается, когда вы запускаете свой экземпляр django. Если вы используете apache, это, вероятно, сработает, потому что в некоторых конфигурациях apache отменяет ваше приложение django при каждом запросе, но все же вы можете найти себя однажды, просматривая свой код и пытаясь выяснить, почему это вычисляется не так, как вы ожидаете .
Правильный способ сделать это - передать вызываемый объект аргументу по умолчанию. Это может быть функция datetime.today или ваша пользовательская функция. Затем он оценивается каждый раз, когда вы запрашиваете новое значение по умолчанию.
источник
get_deadline(my_parameter)
?deadline
снова удалите поле, одновременно удаливget_deadline
функцию? Я удалил поле с функцией для значения по умолчанию, но теперь Django вылетает при запуске после удаления функции. Я мог бы вручную отредактировать миграцию, что в данном случае было бы нормально, но что, если бы вы просто изменили функцию по умолчанию и захотели удалить старую функцию?Между следующими двумя конструкторами DateTimeField есть важное различие:
Если вы используете
auto_now_add=True
в конструкторе, datetime, на который ссылается my_date, будет «неизменным» (устанавливается только один раз, когда строка вставляется в таблицу).С
auto_now=True
, однако, значение даты и времени будет обновляться каждый раз , когда объект будет сохранен.В какой-то момент для меня это определенно было ловушкой. Для справки документы здесь:
https://docs.djangoproject.com/en/dev/ref/models/fields/#datetimefield
источник
Иногда вам может потребоваться доступ к данным модели после создания новой пользовательской модели.
Вот как я генерирую токен для каждого нового профиля пользователя, используя первые 4 символа их имени пользователя:
источник
Вы не можете сделать это напрямую; значение по умолчанию оценивается при оценке определения функции. Но есть два пути обойти это.
Во-первых, вы можете каждый раз создавать (а затем вызывать) новую функцию.
Или, проще говоря, просто используйте специальное значение, чтобы отметить значение по умолчанию. Например:
Если
None
- это вполне разумное значение параметра, и нет другого разумного значения, которое вы могли бы использовать вместо него, вы можете просто создать новое значение, которое определенно выходит за пределы домена вашей функции:В некоторых редких случаях, вы пишете мета-код , который действительно нужно , чтобы быть в состоянии взять абсолютно ничего, даже, скажем,
mydate.func_defaults[0]
. В этом случае вам нужно сделать что-то вроде этого:источник
myfunc
функция состоит в том, чтобы брать (и печатать) adatetime
; вы изменили его, поэтому его нельзя использовать таким образом.Передайте функцию как параметр вместо передачи результата вызова функции.
То есть вместо этого:
Попробуй это:
источник
print datetime.now()
безоговорочно.datetime.now
функция. Но любой пользователь, который передает значение, отличное от значения по умолчанию, будет передавать дату и время, а не функцию.foo = datetime.now(); myfunc(foo)
подниметTypeError: 'datetime.datetime' object is not callable
. Если бы я действительно хотел использовать вашу функцию, мне пришлось бы сделать что-то вродеmyfunc(lambda: foo)
этого, что не является разумным интерфейсом.