[django] Django 모델 필드의 기본값을 함수 호출 / 호출 가능으로 설정하는 방법 (예 : 모델 객체 생성 시간과 관련된 날짜)

편집 :

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에서 모델 필드를 만들 때 함수를 정의하지 않으므로 함수 기본값은 무관합니다.

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))

이 마지막 줄은 함수를 정의하지 않습니다. 클래스에 필드를 만드는 함수를 호출합니다.

장고 1.7 이전

Django를 사용하면 callable을 default로 전달할 수 있으며 원하는대로 매번 호출 할 수 있습니다.

from datetime import datetime, timedelta
class MyModel(models.Model):
  # default to 1 day from now
  my_date = models.DateTimeField(default=lambda: datetime.now() + timedelta(days=1))

Django 1.7 이상

Django 1.7 이후로 람다를 기본값으로 사용하지 않는 것이 좋습니다 (@stvnw 주석 참조). 이를 수행하는 적절한 방법 은 필드 앞에 함수를 선언하고 arg라는 default_value의 콜러 블로 사용하는 것입니다.

from datetime import datetime, timedelta

# default to 1 day from now
def get_default_my_date():
  return datetime.now() + timedelta(days=1)

class MyModel(models.Model):
  my_date = models.DateTimeField(default=get_default_my_date)

아래 @simanas 답변에 대한 자세한 정보


답변

이것은 default=datetime.now()+timedelta(days=1)절대적으로 잘못되었습니다!

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)


답변

다음 두 DateTimeField 생성자 간에는 중요한 차이점이 있습니다.

my_date = models.DateTimeField(auto_now=True)
my_date = models.DateTimeField(auto_now_add=True)

auto_now_add=True생성자에서 사용하는 경우 my_date가 참조하는 datetime은 “불변”입니다 (행이 테이블에 삽입 될 때 한 번만 설정 됨).

으로는 auto_now=True, 그러나, 날짜 시간 값은 객체가 저장 될 때마다 업데이트됩니다.

이것은 한 번에 나에게 확실히 맞았습니다. 참고로 문서는 다음과 같습니다.

https://docs.djangoproject.com/en/dev/ref/models/fields/#datetimefield


답변

새 사용자 모델을 만든 후 모델 데이터에 액세스해야하는 경우가 있습니다.

사용자 이름의 처음 4자를 사용하여 각 새 사용자 프로필에 대한 토큰을 생성하는 방법은 다음과 같습니다.

from django.dispatch import receiver
class Profile(models.Model):
    auth_token = models.CharField(max_length=13, default=None, null=True, blank=True)


@receiver(post_save, sender=User) # this is called after a User model is saved.
def create_user_profile(sender, instance, created, **kwargs):
    if created: # only run the following if the profile is new
        new_profile = Profile.objects.create(user=instance)
        new_profile.create_auth_token()
        new_profile.save()

def create_auth_token(self):
    import random, string
    auth = self.user.username[:4] # get first 4 characters in user name
    self.auth_token =  auth + ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits + string.ascii_lowercase) for _ in range(random.randint(3, 5)))


답변

직접 할 수는 없습니다. 기본값은 함수 정의가 평가 될 때 평가됩니다. 그러나 주위에는 두 가지 방법이 있습니다.

첫째, 매번 새 함수를 생성 한 다음 호출 할 수 있습니다.

또는 더 간단하게 특수 값을 사용하여 기본값을 표시하십시오. 예를 들면 :

from datetime import datetime
def mydate(date=None):
  if date is None:
    date = datetime.now()
  print date

경우 None완벽하게 합리적인 매개 변수 값이, 그리고 당신이 그 자리에 사용할 수있는 다른 합리적인 가치가 없습니다, 당신은 당신의 함수의 도메인 외부 확실히의 새 값을 생성 할 수 있습니다 :

from datetime import datetime
class _MyDateDummyDefault(object):
  pass
def mydate(date=_MyDateDummyDefault):
  if date is _MyDateDummyDefault:
    date = datetime.now()
  print date
del _MyDateDummyDefault

드문 경우에, 당신은 정말로 무엇이든 취할 수 있어야하는 메타 코드를 작성하고 있습니다 mydate.func_defaults[0]. 이 경우 다음과 같이해야합니다.

def mydate(*args, **kw):
  if 'date' in kw:
    date = kw['date']
  elif len(args):
    date = args[0]
  else:
    date = datetime.now()
  print date


답변

함수 호출의 결과를 전달하는 대신 매개 변수로 함수를 전달하십시오.

즉,이 대신 :

def myfunc(date=datetime.now()):
    print date

이 시도:

def myfunc(date=datetime.now):
    print date()


답변