記Django數據庫遷移過程當中遇到的一些問題

首先描述一下問題,Django 數據庫使用的mysql, 而後開始沒注意,沒建一個default庫,就把第一個數據庫當成默認的了,結果Django的admin相關的那些表,都自動生成到這個庫裏了,如今想遷移出來,放到一個新的數據庫裏,遇到的問題就是,migration是成功的,可是遷移的時候就是不成功

最終問題是解決了,可能緣由有如下幾個:python

1. 我發現個人urls.py 文件中,有兩個不一樣路徑對應了一個相同的試圖函數,其實就是寫了兩個url來對應admin, 而後我把這兩個註釋了一個,最後居然就行了,反正我是不會相信是這個問題致使的mysql

2. 最開始的時候是使用sqlite的,因此服務器上還有sqlite數據庫文件,我把它刪掉了
3. 當我在數據庫手動清空django_migrations表的時候,使用的delete命令,刪掉數據後,id仍是從以前的順序排,後來換成了直接用truncate命令清空的數據表sql

4. 我單獨建了一個default數據庫,爲了把Django自帶的哪些admin,session, auth 這些表單獨放到一個數據庫,我如今看來,問題出在這的可能性最大, 應該是還有個地方存migrations文件的,因此每次遷移,都沒有刪掉這個文件裏的內容,致使出錯數據庫



首先, 你得保證,不是migrations文件夾中的文件致使的衝突,若是當你遷移數據庫的時候,報錯說是xx表不存在,或者xx表已存在,首先應該想到的就是解決一下這個問題,固然最暴力的方法就是
1. 刪除這個文件夾下的除了__init__.py文件以外的全部文件;django

2. 從數據庫中刪掉django_migrations表中的數據;服務器

固然若是你能找到衝突的那條記錄,只刪那一條記錄是最好的

session

刪除成功後,在python manage.py makemigrations 
  python manage.py migrate

而後記錄一下Django使用mysql, 使用多數據庫時應該注意的一些地方:
首先要在settings中配置好多個數據庫,app

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中引用:url

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"      
相關文章
相關標籤/搜索