2011-07-27 4 views
7

BlogPost이라는 Django 모델이 있습니다. 처음에는 Meta.verbose_name없이 코딩되었습니다. ./manage.py syncdb 시간에 "블로그 게시물"이라는 이름의 ContentType이 자동으로 생성됩니다. 잠시 후 Meta.verbose_name "블로그 게시물"이 추가됩니다.verbose_name이 변경되면 모델의 ContentType을 어떻게 자동 업데이트합니까?

지금은 차이가있다 : ContentType는 "블로그 게시물"라고, 모델 "블로그 게시물"의 자세한 이름으로가는 동안,이 차이는, 예를 들어, 일반적인 관계를 사용하는 프레임 워크에 표시됩니다 댓글 '관리자. ContentType의 이름을 변경하여이 상황을 해결하고 싶지만 손으로 ​​(분명한 이유로) 또는 이전을 통해 (다른 작업으로 마이그레이션하지 않으므로) 수행하고 싶지는 않습니다. Meta.verbose_name은 코드 변경).

Meta.verbose_name 변경시 ContentType의 이름을 어떻게 업데이트 하시겠습니까?

답변

10

답변 : 나 자신도 작은 post_migrate 신호로 처리했습니다. South를 사용하지 않는 경우, 동일한 방법으로 post_syncdb 신호를 사용할 수 있습니다. 이 코드에 대한 모든 의견을 보내 주시면 감사하겠습니다. 그것은 다음과 같습니다로

from django.contrib.contenttypes.models import ContentType 
from django.utils.functional import Promise 

from south.signals import post_migrate 
# or if using django >=1.7 migrations: 
# from django.db.models.signals import post_migrate 

def update_contenttypes_names(**kwargs): 
    for c in ContentType.objects.all(): 
     cl = c.model_class() 
     # Promises classes are from translated, mostly django-internal models. ignore them. 
     if cl and not isinstance(cl._meta.verbose_name, Promise): 
      new_name = cl._meta.verbose_name 
      if c.name != new_name: 
       print u"Updating ContentType's name: '%s' -> '%s'" % (c.name, new_name) 
       c.name = new_name 
       c.save() 

post_migrate.connect(update_contenttypes_names, dispatch_uid="update_contenttypes") 
+0

나를 위해 훌륭한 작품! BTW, 아마도 이것을 대답으로 표시해야합니다 :) – Dave

+0

자세한 이름으로 특수 문자를 사용하면'new_name = cl._meta.verbose_name.decode ('utf-8')' –

+0

을 사용하고 싶습니다. 나처럼 궁금해 ** 어디에서이 코드를 넣을지 **, app-level'__init __. py'는 장소입니다. –

1

또 다른 방법은, ContentType.__str__ 메소드를 오버라이드 (override)하는 것입니다

: 그래서

def __str__(self): 
    # self.name is deprecated in favor of using model's verbose_name, which 
    # can be translated. Formal deprecation is delayed until we have DB 
    # migration to be able to remove the field from the database along with 
    # the attribute. 
    # 
    # We return self.name only when users have changed its value from the 
    # initial verbose_name_raw and might rely on it. 
    model = self.model_class() 
    if not model or self.name != model._meta.verbose_name_raw: 
     return self.name 
    else: 
     return force_unicode(model._meta.verbose_name) 

당신은 이전 버전과의 호환성을 어떤 종류의가 필요하지 않은 경우, 당신은 그것을 다시 작성할 수 있습니다

from django.contrib.contenttypes.models import ContentType 
from django.utils.encoding import force_unicode 

def contenttype_as_str(self): 
    return force_unicode(self.model_class()._meta.verbose_name) 

ContentType.__str__ = contenttype_as_str 

다소 까다 롭지 만 더 간단하다고 생각합니다. Django 1.4.1 force_textforce_unicode 대신 사용됩니다.

관련 문제