定义自定义post_migrate信号

时间:2015-09-07 22:29:01

标签: django django-signals django-migrations

我正在为我的项目进行某种重构,我依赖于django django.contrib.auth.models.Permission模型。到目前为止,我使用post_save信号为每个新用户定义权限,因此在创建用户时,我使用user.user_permissions.add(the_permission)分配他们的权限,这非常有效。

现在我想使用django.contrib.auth.models.Group模型来区分用户应具有的权限。

这是我的代码:

from django.apps import AppConfig
from django.db.models.signals import post_migrate
from django.contrib.auth.models import Group, Permission


def create_group(name, permissions):
    group = Group.objects.create(name=name)
    [group.permissions.add(permission) for permission in permissions]


def define_company_groups(sender, **kwargs):
    permissions = [
        Permission.objects.get(codename='add_mymodel'),
        Permission.objects.get(codename='change_mymodel'),
    ]
    create_group('managers', permissions)


class MyAppConfig(AppConfig):
    name = 'players'
    verbose_name = 'The players app'

    def ready(self):
        post_migrate.connect(define_company_groups, sender=self)

在定义此代码之后,我希望在调用./manage.py migrate之后,应该触发此处理程序。但它并没有发生,我所得到的只是:

Running post-migrate handlers for application players
Adding permission 'players | mymodel | Can add mymodel'
Adding permission 'companies | company | Can change mymodel'
Adding permission 'companies | company | Can delete company'

我发现这篇https://groups.google.com/forum/#!topic/django-developers/8MdaWtJp4VQ文章,他们说我应该在一个名为management.py的文件中定义我的post_migrate处理程序(既不包括models.py文件中的代码),但不能正常工作。< / p>

最后,我的问题在这里:我应该在哪里将此代码用于我的自定义post_migrate信号?

提前致谢。

3 个答案:

答案 0 :(得分:9)

Django docs建议在app config的ready方法中连接post_migrate信号。在您更新文档之前,您链接到的Google论坛已过期。

您还需要在INSTALLED_APPS设置中specify the app config

INSTALLED_APPS = [
    'myapp.apps.MyAppConfig',
    # ...
]

配置应用的另一种方法是在应用的default_app_config中使用__init__.py。见Configuring Applications。但另一种方式(AppConfig的虚线路径)是首选。

答案 1 :(得分:1)

信号post_migrate与其他信号不同。 './manage.py'命令将不会执行来自apps.py文件或signals.py文件的代码 要执行此信号,请将其放置在models.py文件中。 然后您将获得理想的结果

答案 2 :(得分:1)

我之前已经做了另一个问题的post_migrate示例。我将写下它的解决方案。也许会对您有帮助。

# in apps.py

...
from django.conf import settings
from django.db.models.signals import post_migrate

def create_default_site_profile(sender, **kwargs):
    """after migrations"""
    from django.contrib.sites.models import Site
    from core.models import SiteProfile

    site = Site.objects.get(id=getattr(settings, 'SITE_ID', 1))

    if not SiteProfile.objects.exists():
        SiteProfile.objects.create(site=site)

class CoreConfig(AppConfig):
    name = 'core'

    def ready(self):
        post_migrate.connect(create_default_site_profile, sender=self)
        
        # if you have other signals e.g. post_save, you can include it 
        # like the one below.
        from .signals import (create_site_profile)