Django 同步权限失败原因

2018-02-28  本文已影响72人  大富帅

同步model的权限语句

migrate [<app_label> [<migrationname>]]

官网文档: https://docs.djangoproject.com/en/1.8/ref/django-admin/#migrate-app-label-migrationname

添加Djando自定义权限

添加的时候,在model的meta里面添加

class Task(models.Model):
    ...
    class Meta:
        # 三个自定义权限
        permissions = (
            ("view_task", "Can see available tasks"),
            ("change_task_status", "Can change the status of tasks"),
            ("close_task", "Can remove a task by setting its status as closed"),
        )
   connection_name = 'mipay'

然后执行:

 python manage.py migrate 

按官网的文能说,这样就能同步权限,但是我执行这个命令并没有产生任何效果。
原因是,这个命令还有一个可选参数 --database , 如果不填的话默认default, 这个是settings.py里面的DATABASES配置里面默认的那个配置,也是数据库映射别名(alias)

所以刚才这个命令,只是会对default 的数据库(也就是我们业务的owan数据库产生效果)
然后我下面加上数据库参数, 因为这个表是mipay数据库的,我加上--database=mipay

 python manage.py migrate  --database=mipay

依然不生效,为什么不是已经指定DB了吗,为什么还不生效,auth_permission还是没有新增权限记录。

查了很久才发现,这个--database是指定要插入数据的DB,而不是这个model所属的DB,现在我们是要插入auth_permission表,那么这个表是属于owan_admin这个DB的,所以--database要执行这个DB才生效,settings里面admin是owan_adminDB的配置alias,
所以最后执行这个命令成功更新了权限

 python manage.py migrate  --database=admin

延伸:Django 多DB路由

上面我们的model定义的时候,会用一个类属性connection_name来指定model所属的DB,注意,
这个connection_name不是Django提供的指定DB的字段,之所以我们可以这样指定,是因为我们注册了一个DB的router ,参考文档:https://docs.djangoproject.com/en/2.0/topics/db/multi-db/
这个router主要包括三个方法

对于读逻辑: 如果model类定义有connection_name属性,那么它的主DB就是这个,从DB就是这个属性后面拼接_slave,读的时候,读从库。比如connection_name=mipay, 那么读的时候会读mipay_slave这个DB setting。

对于写逻辑:直接写进connection_name属性这个主库DB
事例

# from django.db import connections
from django.conf import settings

ADMIN_DATABASE_PREFIX_LIST = ["django", "utils", "auditlog"]


class DBRouter(object):
    """可以按照model里面的connection_name来设置要读的数据库"""
    def db_for_read(self, model, **hints):
        # 对于django内置的表,全部使用另外一个表
        db_name = None
        prefix = model.__module__.split('.')[0]
        if prefix in ADMIN_DATABASE_PREFIX_LIST:
            db_name = settings.ADMIN_DATABASE
            # 如果有配置从库,使用从库进行读操作
            if settings.READ_FROM_SLAVE:
                slave_db_name = "%s_slave" % db_name
                if slave_db_name in settings.DATABASES:
                    db_name = slave_db_name
        elif hasattr(model, 'connection_name'):
            db_name = model.connection_name
            # 如果有配置从库,使用从库进行读操作
            if settings.READ_FROM_SLAVE:
                slave_db_name = "%s_slave" % model.connection_name
                if slave_db_name in settings.DATABASES:
                    db_name = slave_db_name
        elif not hasattr(model, 'connection_name'):
            if 'default_slave' in settings.DATABASES:
                db_name = 'default_slave'
        return db_name

    def db_for_write(self, model, **hints):
        db_name = 'default'
        prefix = model.__module__.split('.')[0]
        if prefix in ADMIN_DATABASE_PREFIX_LIST:
            db_name = settings.ADMIN_DATABASE
        elif hasattr(model, 'connection_name'):
            db_name = model.connection_name
        return db_name

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        model = hints.get("model")
        #print model_name, type(model_name)
        if model_name == 'recharge':
            print db
        if not model:
            return False
        prefix = model.__module__.split('.')[0]
        if prefix in ADMIN_DATABASE_PREFIX_LIST:
            if db == settings.ADMIN_DATABASE:
                return True
            else:
                return False
        elif hasattr(model, 'connection_name'):
            if model.connection_name == db:
                return True
            else:
                return False
        else:
            if db == "default":
                return True
            else:
                return False
        return None

写完这个router记得要在setting里面加上配置,注册这个router

DATABASE_ROUTERS = [
    'utils.db.router.DBRouter'
]
上一篇下一篇

猜你喜欢

热点阅读