当verbose_name更改时,如何自动更新模型的ContentType?

Nik*_*nko 7 django django-models django-contenttypes

给出的是Django模型BlogPost.首先,它没有编码Meta.verbose_name.此时./manage.py syncdb,会自动创建ContentType名为" 博客帖子 " 的名称.在稍后的某个时间点,添加Meta.verbose_name了" 博客帖子 ".

现在存在差异:ContentType被称为" 博客帖子 ",而模型名称为" 博客帖子 ",这种差异显示在使用通用关系的任何框架中,例如在评论的管理员中.我想通过更改名称来纠正这种情况ContentType,但是,我不想手动(出于显而易见的原因)或通过迁移(因为我不迁移任何其他东西,Meta.verbose_name只是一个代码)更改).

如何ContentTypeMeta.verbose_name更改时更新名称?

Nik*_*nko 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")
Run Code Online (Sandbox Code Playgroud)