2014-10-24 2 views
9

나는 Django 1.7 마이그레이션을 사용하며, 특히 새로 생성 된 데이터베이스에 초기 데이터를 채우고 싶습니다. 따라서 저는 이것을 위해 데이터 이전을 사용합니다. 그것은 다음과 같습니다Django 마이그레이션에서 신호를 보내려면 어떻게해야합니까?

@receiver(signals.post_save, sender=django.contrib.auth.models.User) 
def add_user_details(sender, instance, created, **kwargs): 
    if created: 
     my_app.UserDetails.objects.create(user=instance) 

그러나 :

동시에
def populate_with_initial_data(apps, schema_editor): 
    User = apps.get_model("auth", "User") 
    new_user = User.objects.create(username="nobody") 

class Migration(migrations.Migration): 

    ... 

    operations = [ 
     migrations.RunPython(populate_with_initial_data), 
    ] 

, 나는 모든 새 사용자에 대한 UserDetails 모델의 인스턴스를 갖고 싶어이 신호는 이동 외부에만 작동합니다 . 그 이유는 apps.get_model("auth", "User")이 신호가 보내지지 않는 django.contrib.auth.models.User과 다를만큼 충분하지 않기 때문입니다. 내가 수동으로 수행하려고 할 경우, 다음과 같이, 그것은 실패

: 다음, 신호 핸들러가 새로운 UserDetails역사 User에 O2O으로 가리키는 만들려고하기 때문에

signals.post_save.send(django.contrib.auth.models.User, instance=julia, created=True) 

이 실패

ValueError: Cannot assign "<User: User object>": "UserDetails.user" must be a "User" instance. 

험머.

좋아, 신호 처리기를 직접 호출 할 수 있습니다. 그러나 키워드 인수 (및 필요한 다른 기록 클래스)에 역사적인 UserDetails 클래스를 전달해야했습니다. 게다가 UserDetails이있는 앱은이 데이터 이전을 지원하는 앱이 아니므로 쉽게 손상 될 수있는 추한 종속성이 될 수 있습니다. UserDetails 앱이 INSTALLED_APPS에서 제거 된 경우

이 코드는 현재 추한 코드와 FixMe 주석으로 해결해야하는 현재의 제한 사항입니까? 아니면 데이터 마이그레이션에서 신호를 보내는 방법이 있습니까?

+0

해결 방법을 찾으셨습니까? –

+2

예, signal.post_migrate를 사용합니다. *이 * 호출되기 때문입니다. 그러나 여전히 필요하지 않은 코드가 필요합니다. –

+0

이 질문은 대답이없는 장고 질문의 맨 위에 있으므로 답변을 게시하고 본인의 대답을 받아 들여야합니다. – dotcomly

답변

3

마이그레이션을 실행할 때 UserDetails이이 마이그레이션을 작성했을 때와 실제로 다를 수 있기 때문에이 작업을 수행 할 수 없으며 수행해서는 안됩니다. django (및 south)가 마이그레이션을 작성했을 때와 동일한 "고정 된 모델"을 사용하는 이유가 여기에 있습니다.

"불행하게도"당신은 마이그레이션을 할 때 신호 코드를 고정시켜야합니다.을 쓸 때의 동작을 유지해야합니다.

오늘은이 할 수 : : 그런 다음

class UserDetails(models.Model): 
    user = models.ForeignKey(...) 
    typo_fild = models.CharField(...) 

@receiver(signals.post_save, sender=django.contrib.auth.models.User) 
def add_user_details(sender, instance, created, **kwargs): 
    if created: 
     UserDetails.objects.create(user=instance, typo_fild='yo') 

을, 나는이가 마이그레이션 내부의 실제 모델 (또는 신호 등)를 사용하지 않는 중요한 이유

간단한 exemple 이해하기 새로운 사용자를 생성하는 데이터 마이그레이션 ("populate_users"라고 함). 그리고 그 안에 add_user_details의 실행을 강제합니다. 괜찮습니다 : 오늘 일합니다.

내일, 내 typo_fild ->typo_field 내에서 UserDetailsadd_user_details을 수정합니다. 새 스키마 이주가 작성되어 데이터베이스의 필드 이름을 바 Y십시오.새 사용자가 생성 될 때, 그것은 아직 데이터베이스에 존재하지 않는 필드 "typo_field"느릅 나무와 새 UserDetails를 만들려고하기 때문에이 시점에서

, 내 마이그레이션 "populate_users" 을 실패합니다 :이 필드는 다음 마이그레이션으로 DB에서 이름이 바뀝니다.

따라서 언제든지 좋은 마이그레이션을 유지하려면 마이그레이션 내에서 add_user_details의 동작을 복사해야합니다. add_user_details의 동결은 동결 모델 UserDetails을 통해 apps.get_model("myapp", "UserDetails")을 사용해야하고 typo_fild이 새롭게 UserDetails으로 만들어져 동결됩니다.

+1

원한다면 언제든지 발로 슛을 할 수 있습니다. 결국, 다른 시그널들이 보내지고, 나는이 문제를 해결하기 위해 이것을 사용한다. 모델에 문제가있는 변경 사항을 적용하면 신호 처리기에서 인트로 스펙 션을 사용할 수 있습니다. "빈번한 사건을 단순하게하고 드문 사건을 가능하게하십시오." –

관련 문제