zoukankan      html  css  js  c++  java
  • 记Django数据库迁移过程中遇到的一些问题

    首先描述一下问题,Django 数据库使用的mysql, 然后开始没注意,没建一个default库,就把第一个数据库当成默认的了,结果Django的admin相关的那些表,都自动生成到这个库里了,现在想迁移出来,放到一个新的数据库里,遇到的问题就是,migration是成功的,但是迁移的时候就是不成功

    最终问题是解决了,可能原因有以下几个:

    1. 我发现我的urls.py 文件中,有两个不同路径对应了一个相同的试图函数,其实就是写了两个url来对应admin, 然后我把这两个注释了一个,最后竟然就好了,反正我是不会相信是这个问题导致的

    2. 最开始的时候是使用sqlite的,所以服务器上还有sqlite数据库文件,我把它删掉了
    3. 当我在数据库手动清空django_migrations表的时候,使用的delete命令,删掉数据后,id还是从之前的顺序排,后来换成了直接用truncate命令清空的数据表

    4. 我单独建了一个default数据库,为了把Django自带的哪些admin,session, auth 这些表单独放到一个数据库,我现在看来,问题出在这的可能性最大, 应该是还有个地方存migrations文件的,所以每次迁移,都没有删掉这个文件里的内容,导致出错



    首先, 你得保证,不是migrations文件夹中的文件导致的冲突,如果当你迁移数据库的时候,报错说是xx表不存在,或者xx表已存在,首先应该想到的就是解决一下这个问题,当然最暴力的方法就是
    1. 删除这个文件夹下的除了__init__.py文件之外的所有文件;

    2. 从数据库中删掉django_migrations表中的数据;

    当然如果你能找到冲突的那条记录,只删那一条记录是最好的

    删除成功后,在python manage.py makemigrations 
      python manage.py migrate

    然后记录一下Django使用mysql, 使用多数据库时应该注意的一些地方:
    首先要在settings中配置好多个数据库,

    DATABASES = {
        # 'default': {
        #     'ENGINE': 'django.db.backends.sqlite3',
        #     'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        # },
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'dja......t',
            'USER': 'root',
            'PASSWORD': 't.....',
            'HOST': '34.....',
            'PORT': '3306',
            "OPTIONS": {
                "init_command": "SET sql_mode='STRICT_TRANS_TABLES'",
    
            }
    
        },
        'slots_config': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'slo....',
            'USER': 'root',
            'PASSWORD': 't......',
            'HOST': '34.2.......',
            'PORT': '3306',
            "OPTIONS": {
                "init_command": "SET sql_mode='STRICT_TRANS_TABLES'",
                # 'charset': 'utf8mb4'
            }
    
        },
        'permission': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'sl.....',
            'USER': 'root',
            'PASSWORD': 't....',
            'HOST': '34.237....',
            'PORT': '3306',
            "OPTIONS": {
                "init_command": "SET sql_mode='STRICT_TRANS_TABLES'",
                # 'charset': 'utf8mb4'
            }
        },
    }

    我的做法是一个app配一个数据库,所以要把app和数据库对应起来,写一个map映射关系

    DATABASE_APPS_MAPPING = {
        # "default": "default",
        "permission_control": "permission",
        "slo...": "s.....",
        "auth": "default",
        "session": "default",
        "contenttypes": "default",
        "admin": "default",
    }

    同时,还需要一个路由,来指定model 和 数据库之间的路由关系,在settings同级目录下写一个文件,从settings中引用:

    DATABASE_ROUTERS = ['s......nd.database_router.DatabaseAppsRouter']  # 数据库路由规则

    文件内容:

    from django.conf import settings
    
    DATABASE_MAPPING = settings.DATABASE_APPS_MAPPING
    
    
    class DatabaseAppsRouter(object):
        """
        A router to control all database operations on models for different
        databases.
    
        In case an app is not set in settings.DATABASE_APPS_MAPPING, the router
        will fallback to the `default` database.
    
        Settings example:
    
        DATABASE_APPS_MAPPING = {'app1': 'db1', 'app2': 'db2'}
        """
    
        def db_for_read(self, model, **hints):
            """"Point all read operations to the specific database."""
            if model._meta.app_label in DATABASE_MAPPING:
                return DATABASE_MAPPING[model._meta.app_label]
            return None
    
        def db_for_write(self, model, **hints):
            """Point all write operations to the specific database."""
            if model._meta.app_label in DATABASE_MAPPING:
                return DATABASE_MAPPING[model._meta.app_label]
            return None
    
        def allow_relation(self, obj1, obj2, **hints):
            """Allow any relation between apps that use the same database."""
            db_obj1 = DATABASE_MAPPING.get(obj1._meta.app_label)
            db_obj2 = DATABASE_MAPPING.get(obj2._meta.app_label)
            if db_obj1 and db_obj2:
                if db_obj1 == db_obj2:
                    return True
                else:
                    return False
            return None
    
        def allow_syncdb(self, db, model):
            """Make sure that apps only appear in the related database."""
    
            if db in DATABASE_MAPPING.values():
                return DATABASE_MAPPING.get(model._meta.app_label) == db
            elif model._meta.app_label in DATABASE_MAPPING:
                return False
            return None
    
        def allow_migrate(self, db, app_label, model=None, **hints):
            """
            Make sure the auth app only appears in the 'auth_db'
            database.
            """
            if db in DATABASE_MAPPING.values():
                return DATABASE_MAPPING.get(app_label) == db
            elif app_label in DATABASE_MAPPING:
                return False
            return None

    ok, 这样就按app来区分了不同的数据库
    这样在views中,操作数据的时候,也不用use 这种语法了,能自动根据app去连接对应的数据库
    哦,对了,在model中,每个表都要明确指定app名称,类似这样

    class App(models.Model):
        """
        app表
        """
    
        caption = models.CharField(verbose_name="应用名", null=True, blank=True, max_length=64)
        app_id = models.IntegerField(verbose_name="app_id")
        product = models.ForeignKey(Product, verbose_name="所属产品", related_name="apps")
        role = models.ManyToManyField(to="Role", verbose_name="拥有角色", blank=True)
    
        class Meta:
            app_label = "permission_control"    # 这里,指明app名称,用来对应app 和 数据库的map表
            db_table = "app"      
  • 相关阅读:
    写360搜索网页总结
    display和position以及其余标签的使用
    MySQL中的 show index命令
    MySQL中查看索引使用情况
    分布式存储容错原理
    MySQL中通过trace分析优化器跟踪SQL
    MySQL中的 show profile 分析sql
    MySQL 中的 dual表
    Every derived table must have its own alias(sql语句错误解决方法)
    MySQL 中的 explain 语句各字段解释
  • 原文地址:https://www.cnblogs.com/zhang-can/p/9180265.html
Copyright © 2011-2022 走看看