• Django 动态修改库名


    需求场场景

    一个项目需要把数据库按天存档,所以每天都会创建一个新的库,第二天切换到新库,名的明称是以日期命名

    这是一个独立使用Django ORM的项目

    setting.py

    import os
    import sys
    from datetime import datetime
    
    # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
    
    
    # 生成当天db名
    def trade_db_file():
        now = datetime.now()
        now_str = now.strftime('%Y-%m-%d')
        return "{}_pos.db".format(now_str)
    
    
    def cashier_db_file():
        return "cashier.db"
    
    # sqlite 配置
    def make_config(db_file):
        return {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, db_file),
        }
    
    
    def db_full_path(db_file):
        return os.path.join(BASE_DIR, db_file)
    
    
    BASE_DIR = os.path.dirname(__file__)
    sys.path.insert(0, BASE_DIR)
    
    print(__file__)
    print(BASE_DIR)
    
    
    # Quick-start development settings - unsuitable for production
    # See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
    
    # SECURITY WARNING: keep the secret key used in production secret!
    SECRET_KEY = 'lyv+won7%7!=ra!nc160o-x1yz+m%n1jxm)wtw_y1r3%shh@-%'
    
    # SECURITY WARNING: don't run with debug turned on in production!
    DEBUG = True
    
    DATABASE_MAPPING = {
        "cashier": "cashier_db",
        "trade": "default"
    }
    
    # 多库路由
    DATABASE_ROUTERS = ['models.database.router.DatabaseAppsRouter']
    
    # Application definition
    
    # 两个APP
    INSTALLED_APPS = [
        "models.database.trade",   
        'models.database.cashier',
    ]
    
    # Database
    # https://docs.djangoproject.com/en/2.1/ref/settings/#databases
    
    # 默认库配置
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, trade_db_file()),
        },
        'cashier_db': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, cashier_db_file()),
        }
    }
    
    

    router.py 这个是db路由文件,决定了迁移,读写等操作的路由

    
    from .settings import DATABASE_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'}
        """
    
        default_database = "default"
    
        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]
            else:
                return self.default_database
    
        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]
            else:
                return self.default_database
    
        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) or self.default_database
            db_obj2 = DATABASE_MAPPING.get(obj2._meta.app_label) or self.default_database
            if db_obj1 and db_obj2:
                if db_obj1 == db_obj2:
                    return True
                else:
                    return False
            else:
                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
    
    

    /models/database/init.py

    import os
    
    from django.db.utils import load_backend
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "models.database.settings")
    from django.apps import apps
    from django.conf import settings
    from django.core.management import call_command
    from django.core import checks
    
    
    debug = print
    
    apps.populate(settings.INSTALLED_APPS)
    
    
    def check_error():
        errors = checks.run_checks()
        if errors:
            for error in errors:
                debug(f"Error:{error}")
            return True
        else:
            return False
    
    
    def migrate(app_name: str):
        if check_error():
            return
    
        database = settings.DATABASE_MAPPING.get(app_name) or "default"
        call_command("migrate", app_name, database=database)
    
    
    def make_migrations(app_name: str):
        call_command("makemigrations", app_name)
    
    
    def init_date_db(date: str = "2020-02-02"):
        from models.database.settings import make_config
        from django.db import connections
    
        db = make_config("{}_pos.db".format(date))
        connections.databases[date] = db
        con = connections[date]
        print(con)
    
    
    def init():
        from django.conf import settings
        for app in settings.INSTALLED_APPS:
            name = app.split(".")
            make_migrations(name[-1])
            migrate(name[-1])
    
    

    应用层换库操作

    from models.database import init, init_date_db
    
    # 当天默认库的mirate
    init()
    s = Sale.objects.create(sale_dt="2021-01-15 08:49:01", sale_id=2)
    print(s.sale_id)
    
    # 指定天库的操作
    init_date_db("2021-01-14")
    from models.database.trade.models import Sale
    s = Sale.objects.using("2021-01-14").create(sale_dt="2021-01-15 08:49:01", sale_id=2)
    print(s.sale_id)
    
    
  • 相关阅读:
    实验4-2-4 换硬币 (20分)
    实验4-1-4 求整数的位数及各位数字之和 (15分)
    实验4-1-10 兔子繁衍问题 (15分)
    实验4-1-7 特殊a串数列求和 (20分)
    实验4-1-3 找出最小值 (20分)
    实验4-1-2 求奇数和 (15分)
    实验4-1-1 最大公约数和最小公倍数 (15分)emmm辗转相除法
    实验3-10 高速公路超速处罚 (15分)
    1.使用Lucene开发自己的搜索引擎--倒排索引基础知识
    办公自动化项目从无到有-第三篇系统管理模块
  • 原文地址:https://www.cnblogs.com/onsunsl/p/Django-dynamic-change-database.html
Copyright © 2020-2023  润新知