美文网首页
Django 同步权限失败原因

Django 同步权限失败原因

作者: 大富帅 | 来源:发表于2018-02-28 19:33 被阅读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主要包括三个方法

    • db_for_read 根据model选择读的DB
    • db_for_write 根据model选择写的DB
    • allow_migrate 根据model选择是否允许migrate

    对于读逻辑: 如果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'
    ]
    

    相关文章

      网友评论

          本文标题:Django 同步权限失败原因

          本文链接:https://www.haomeiwen.com/subject/dsbixftx.html