장고 날짜 시간 문제 (default = datetime.now ())


283

아래 db 모델이 있습니다.

from datetime import datetime    

class TermPayment(models.Model):
    # I have excluded fields that are irrelevant to the question
    date = models.DateTimeField(default=datetime.now(), blank=True)

아래를 사용하여 새 인스턴스를 추가합니다.

tp = TermPayment.objects.create(**kwargs)

내 문제 : 데이터베이스의 모든 레코드는 첫 번째 지불 날짜 인 날짜 필드의 값이 동일합니다. 서버가 다시 시작된 후 한 레코드는 새로운 날짜를 가지며 다른 레코드는 첫 번째 레코드와 동일합니다. 일부 데이터가 캐시 된 것처럼 보이지만 어디에서 찾을 수 없습니다.

데이터베이스 : mysql 5.1.25

장고 v1.1.1


1
다음과 같은 함수를 기본값으로 설정할 수 없습니까? : default=datetime.now-참고, now()DateTimeField의 표준은 아니지만 ...
viridis

답변:


597

datetime.now()레코드를 추가 할 때마다가 아니라 모델이 정의 될 때 평가되는 것처럼 보입니다 .

Django에는 이미 수행하려는 작업을 수행하는 기능이 있습니다.

date = models.DateTimeField(auto_now_add=True, blank=True)

또는

date = models.DateTimeField(default=datetime.now, blank=True)

두 번째 예와 현재 가지고있는 것의 차이점은 괄호가 없다는 것입니다. 전달하여 datetime.now괄호없이, 당신은 레코드가 추가 될 때마다 호출되는 실제 함수를 전달한다. 전달 datetime.now()하면 함수를 평가하고 반환 값을 전달하는 것입니다.

자세한 내용은 Django의 모델 필드 참조 에서 확인할 수 있습니다


206
중요 사항 : auto_now_add를 사용하면 관리자가 필드를 편집 할 수
없게됩니다.

7
좋은 답변, 감사합니다. datetime.now를 기본값으로 사용하여보다 복잡한 표현식을 표현하는 방법이 있습니까? 예 : 현재 + 30 일 (다음은 작동하지 않음) expiry = models.DateTimeField(default=datetime.now + timedelta(days=30))
michela

26
@michela datetime.now는 함수이며 함수에 타임 델타를 추가하려고합니다. def now_plus_30(): return datetime.now() + timedelta(days = 30)다음 과 같이 기본값을 설정하기 위해 고유 한 콜백을 정의한 다음models.DateTimeField(default=now_plus_30)
Carson Myers

55
또는 당신은 물론 할 수 있습니다default=lambda: datetime.now()+timedelta(days=30)
Michael Mior

34
주의 auto_now_add을 사용하는 것을 NOT 필드가 항상 동일 할 것이기 때문에 디폴트를 사용하는 것과 같은 지금 (편집 불가) .. 나는이 이미했다 알지만, 그것은 '관리'페이지의 단지 METTER 아닙니다에
VAShhh

115

사용하는 대신 datetime.now실제로 사용해야합니다.from django.utils.timezone import now

참고:

다음과 같이하십시오 :

from django.utils.timezone import now


created_date = models.DateTimeField(default=now, editable=False)

13
이것은 매우 중요한 메모입니다! datetime.now를 사용하면 시간대를 인식하지 못하는 현지 날짜 시간을 사용할 수 있습니다. 나중에 auto_now_add시간대를 사용하여 타임 스탬프가 지정된 필드와 비교하면 시간대 차이가 심하여 잘못된 계산을 얻을 수 있습니다.
Iftah

1
이것은 매우 중요하지만 실제로 질문 자체에 답하지는 않습니다.
Czechnology

1
더 나은 방법
Carmine Tambascia

28

django 모델 기본 필드 의 문서 에서 :

필드의 기본값입니다. 이것은 값 또는 호출 가능한 객체 일 수 있습니다. 호출 가능하면 새로운 객체가 생성 될 때마다 호출됩니다.

따라서 다음과 같이 작동합니다.

date = models.DateTimeField(default=datetime.now,blank=True)

1
이것은 django 1.8 이상에서만 가능합니다
David Schumann

@DavidNathan 왜 그런가요? default( django-chinese-docs-14.readthedocs.io/en/latest/ref/models/… ) 에 대한 호출 가능 사용을 포함하여 두 가지 옵션 모두 1.4 또는 그 이전에 존재했다고 생각합니다.
Mark

16

다윗은 정답을 얻었습니다. 괄호 ()는 모델을 평가할 때마다 호출 가능한 timezone.now ()가 호출 되도록합니다 . timezone.now () (또는 순진한 datetime 객체를 사용하는 경우 datetime.now ())에서 ()를 제거하면 다음과 같이됩니다.

default=timezone.now

그런 다음 예상대로 작동합니다.
새 객체는 객체를 만들 때 현재 날짜를 수신하지만 manage.py makemigrations / migrate를 수행 할 때마다 날짜가 무시되지 않습니다.

방금이 문제가 발생했습니다. 다윗에게 감사드립니다.


10

datetime.now()클래스가 생성 될 때 새로운 기록이 데이터베이스에 추가 될하지 않을 경우, 평가됩니다.

원하는 것을 달성하려면이 필드를 다음과 같이 정의하십시오.

date = models.DateTimeField(auto_now_add=True)

이 방법으로 date필드는 각각의 새 레코드에 대한 현재 날짜로 설정됩니다.


6

이것에 대한 대답은 실제로 잘못되었습니다.

자동 입력 값 (auto_now / auto_now_add는 기본값과 동일하지 않음) 기본값은 실제로 새로운 객체인지 사용자가 보는 것입니다. 내가 일반적으로하는 일은 다음과 같습니다.

date = models.DateTimeField(default=datetime.now, editable=False,)

관리자 페이지에서이를 표시하려는 경우 'read_only'로 나열하고 필드 이름을 참조하십시오

read_only = 'date'

기본 값은 일반적으로 편집 할 수 없으므로 달리 지정하지 않는 한 관리 페이지는 편집 할 수없는 항목을 무시합니다. 그러나 기본값 설정과 여기서 중요한 auto_add 구현에는 차이가 있습니다. 그것을 테스트하십시오!


6

datetime.now()클래스가 인스턴스화되면 한 번 평가됩니다. 함수 datetime.now가 리턴되고 THEN이 평가 되도록 괄호를 제거하십시오 . 내 기본값을 설정하는 것과 같은 문제가 있었고 여기에DateTimeField 내 솔루션을 작성했습니다 .


5

함수 정의 아래의 파이썬 언어 참조에서 :

함수 정의가 실행될 때 기본 매개 변수 값이 평가됩니다. 이는 함수가 정의 될 때 표현식이 한 번 평가되며 각 호출에 대해 동일한 "사전 계산 된"값이 사용됨을 의미합니다.

다행히 Django는 다음에 auto_now인수를 사용하면 원하는 것을 수행 할 수있는 방법이 있습니다 DateTimeField.

date = models.DateTimeField(auto_now=True)

DateTimeField에 대해서는 장고 문서를 참조하십시오 .


0

장고 3.0 auto_now_add에서 작동하는 것 같습니다auto_now

reg_date=models.DateField(auto_now=True,blank=True)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.