2011-07-27 48 views
7

鉴于Django模型被称为BlogPost。起初,它的编码没有Meta.verbose_name。在./manage.py syncdb时间,自动创建名称为“博客文章”的ContentType。在稍后的时间点,添加“博客文章”的Meta.verbose_name当verbose_name更改时,如何自动更新模型的ContentType?

现在有一个矛盾:ContentType被称为“博客文章”,而模型的推移的“博客文章”冗长的名字,这种差异使用通用的关系显示在任何框架,例如在评论'管理员。我想通过更改ContentType的名称来纠正这种情况,但是,我不想通过手动(出于显而易见的原因)或通过迁移(因为我不会迁移任何其他东西),Meta.verbose_name只是代码更改)。

如何更新ContentType的名称Meta.verbose_name更改?

回答

10

回答自己的问题:我设法用一个小的post_migrate信号做到这一点。如果您不使用南方,可能完全有可能以相同的方式使用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

对我很好,thx!顺便说一句,你应该把这个标记为答案:) – Dave

+0

如果你在你的详细名称中使用特殊字符,你想使用'new_name = cl._meta.verbose_name.decode('utf-8')' –

+0

如果你想知道像我**放哪里这个代码**,应用程序级'__init __。py'是地方。 –

1

另一种方法是重写ContentType.__str__方法,因为它看起来是这样的:

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_text而不是force_unicode

相关问题