[python] 장고 auto_now 및 auto_now_add

장고 1.1.

나는 models.py에 이것을 가지고있다 :

class User(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

행을 업데이트하면 다음과 같은 결과가 나타납니다.

[Sun Nov 15 02:18:12 2009] [error] /home/ptarjan/projects/twitter-meme/django/db/backends/mysql/base.py:84: Warning: Column 'created' cannot be null
[Sun Nov 15 02:18:12 2009] [error]   return self.cursor.execute(query, args)

내 데이터베이스의 관련 부분은 다음과 같습니다

  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,

이것이 우려의 원인입니까?

추가 질문 : 내 관리 도구에서이 두 필드가 표시되지 않습니다. 예상 되나요?



답변

auto_now속성이 설정된 모든 필드 도 상속 editable=False되므로 관리자 패널에 표시되지 않습니다. 과거에 auto_nowauto_now_add인수를 없애는 것에 대한 이야기가 있었지만 여전히 존재하지만 사용자 정의 save()방법 만 사용하는 것이 좋습니다 .

그래서, 내가 사용하지 않는 것이 좋습니다, 제대로이 작품을 만들기 위해 auto_now또는 auto_now_add대신 자신의 정의 save()가 있는지 확인하는 방법을 created경우에만 업데이트됩니다 id(예 : 항목을 처음 만들 때와 같이) 설정되지 않은, 그리고 업데이트가 modified항목마다 저장됩니다.

Django를 사용하여 작성한 다른 프로젝트와 똑같은 작업을 수행 했으므로 save()다음과 같이 보일 것입니다.

from django.utils import timezone

class User(models.Model):
    created     = models.DateTimeField(editable=False)
    modified    = models.DateTimeField()

    def save(self, *args, **kwargs):
        ''' On save, update timestamps '''
        if not self.id:
            self.created = timezone.now()
        self.modified = timezone.now()
        return super(User, self).save(*args, **kwargs)

도움이 되었기를 바랍니다!

의견에 대한 답변으로 수정 :

오버로드 save()와 이러한 필드 인수에 의존하는 이유 는 두 가지입니다.

  1. 위에서 언급 한 기복은 신뢰성과 함께. 이러한 주장은 Django가 상호 작용하는 방법을 알고있는 각 유형의 데이터베이스가 날짜 / 시간 스탬프 필드를 처리하는 방식에 크게 의존하고 있으며 모든 릴리스간에 중단 및 / 또는 변경되는 것으로 보입니다. (내가 그것들을 모두 제거하라는 요구의 원동력이라고 믿는다).
  2. 그것들은 DateField, DateTimeField 및 TimeField에서만 작동하며이 기술을 사용하면 항목을 저장할 때마다 모든 필드 유형을 자동으로 채울 수 있습니다.
  3. 에 따라 TZ 인식 또는 순진한 개체를 반환하므로 django.utils.timezone.now()vs.를 사용하십시오 .datetime.datetime.now()datetime.datetimesettings.USE_TZ

OP가 오류를 보인 이유를 해결하기 위해 정확히 알지 못하지만 created에도 불구하고 전혀 채워지지 않은 것처럼 보입니다 auto_now_add=True. 나에게 그것은 버그로 눈에 띄는, 위 내 작은 목록의 항목 # 1을 강조 : auto_nowauto_now_add최상의 색다른 있습니다.


답변

그러나 나는 대답에 표현 된 의견 이 다소 구식 이라고 지적하고 싶었습니다 . 더 최근의 토론 (장고 버그 # 7634# 12785 )에 따르면 auto_now 및 auto_now_add는 아무데도 가고 있지 않으며 원래 토론으로 이동하더라도 커스텀 저장에서 RY에 대한 강력한 논쟁을 찾을 수 있습니다 행동 양식.

더 나은 솔루션이 제공되었지만 (맞춤형 필드 유형), 장고로 만들기에 충분한 운동량을 얻지 못했습니다. 세 줄로 직접 작성할 수 있습니다 ( Jacob Kaplan-Moss의 제안입니다 ).

from django.db import models
from django.utils import timezone


class AutoDateTimeField(models.DateTimeField):
    def pre_save(self, model_instance, add):
        return timezone.now()

#usage
created_at = models.DateField(default=timezone.now)
updated_at = models.AutoDateTimeField(default=timezone.now)


답변

부수적 인 질문에 대해 말하기 : 관리자에서이 필드를 보려면 (편집 할 수는 없지만) readonly_fields관리자 클래스에 추가 할 수 있습니다 .

class SomeAdmin(ModelAdmin):
    readonly_fields = ("created","modified",)

글쎄, 이것은 최신 장고 버전에만 적용됩니다 (1.3 이상)


답변

가장 쉬운 (아마도 가장 우아한) 솔루션 default은 호출 가능으로 설정할 수 있다는 사실을 활용하는 것 입니다. 따라서 관리자의 auto_now 특수 처리를 피하려면 다음과 같이 필드를 선언하면됩니다.

from django.utils import timezone
date_filed = models.DateField(default=timezone.now)

timezone.now()기본값이 업데이트 되지 않도록 사용하지 않는 것이 중요합니다 (즉, 코드가로드 될 때만 기본값이 설정 됨). 이 작업을 많이하면 사용자 정의 필드를 만들 수 있습니다. 그러나 이것은 이미 생각하기에 꽤 건조합니다.


답변

다음과 같이 모델 클래스를 변경하면 :

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

그러면이 필드가 관리자 변경 페이지에 나타납니다


답변

내가 읽은 내용과 지금까지 Django에 대한 내 경험에 따르면 auto_now_add는 버그가 있습니다. 나는 jthanism에 동의합니다 — 깨끗한 정상적인 저장 방법을 무시하고 무엇이 문제인지 알고 있습니다. 이제 건조시키기 위해 TimeStamped라는 추상 모델을 만듭니다.

from django.utils import timezone

class TimeStamped(models.Model):
    creation_date = models.DateTimeField(editable=False)
    last_modified = models.DateTimeField(editable=False)

    def save(self, *args, **kwargs):
        if not self.creation_date:
            self.creation_date = timezone.now()

        self.last_modified = timezone.now()
        return super(TimeStamped, self).save(*args, **kwargs)

    class Meta:
        abstract = True

그런 다음이 타임 스탬프 동작을 가진 모델을 원할 때 서브 클래스 만 :

MyNewTimeStampyModel(TimeStamped):
    field1 = ...

관리자에게 필드를 표시하려면 editable=False옵션을 제거하십시오.


답변

이것이 우려의 원인입니까?

아니요, 장고는 모델을 저장하는 동안 자동으로 추가하므로 예상됩니다.

추가 질문 : 내 관리 도구에서이 두 필드가 표시되지 않습니다. 예상 되나요?

이 필드는 자동으로 추가되므로 표시되지 않습니다.

위의 내용에 덧붙여서, synack이 말했듯이, django 메일 링리스트에서 이것을 제거하기위한 토론이있었습니다. 왜냐하면 “잘 설계되지 않았고” “핵”이기 때문입니다

내 각 모델에서 사용자 정의 save ()를 작성하는 것은 auto_now를 사용하는 것보다 훨씬 고통입니다.

분명히 모든 모델에 쓸 필요는 없습니다. 한 모델에 쓰고 다른 모델을 상속 할 수 있습니다.

하지만, auto_add하고 auto_now_add있다, 나는 방법을 자신을 작성하는 것보다 오히려 그들을 사용할 수 있습니다.