zoukankan      html  css  js  c++  java
  • Django多数据库的使用

    源地址:https://blog.csdn.net/qq_39936349/article/details/80761948

    *首先声明,我所用的版本是python3.5和Django2.0.4,公司使用的是Django,没有用restframework。
    一、应用场景

      首先一个Django项目里通常会有多个app,现在很多公司在这多个app中都是共用的一个数据库。在这种场景中是不存在所谓连多个数据库的。那以我的个人经历来说,公司近两个月让我陆陆续续做了一些小的系统(都是用于公司内部数据分拣的),因为每个都很急用,所以就做完一个上线一个,数据库和项目都部在不同服务器上了。直到有一天我们老总把我叫过去:“小肖啊,你抽时间把你做的几个系统合一下,咱们把它合成一个系统。就是登陆以后,出一个系统选择页面,选哪个就进那个系统。”

      之后我一番奋战,把代码什么的合并到一起了。但是,发现数据不在一个库里,王炸!那么就有两种选择:

      1.把所有的模型都通过默认的数据库放在一起,那么这样做就需要把之前处理的数据抽出来,并且对模型进行修改,把一些重复的表名进行一些区分;

      2.是依然让数据存在之前的库里,把这些数据库迁移出来,抽取出Django自建的表,然后通过不同的数据库进行不同操作,这样也做到了不同系统间的数据的隔离。

      所以最后我选用了第二种方案来做这个事情。

     

    二、代码实现

     

      代码中主要是三个部分,settings、models以及自己写的一个类。首先看看我们写的那个类:

     

    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
            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."""
    
    
            """确保身份验证应用程序只出现在“authdb”数据库中。"""
    
            if db in DATABASE_MAPPING.values():
    
                return DATABASE_MAPPING.get(app_label) == db
            elif app_label in DATABASE_MAPPING:
    
                return False
    
            return None

     

    这个类主要是规范了数据库的一些读写操作。要注意,这个文件是放在和settings.py同级的目录下的。代码逻辑比较好理解,我就不解释了。用的时候直接复制粘贴一把梭,然后自己再做一些逻辑处理上的修改就可以了。

      在settings中是配置三个地方,代码如下:

     

    # Database
    # https://docs.djangoproject.com/en/2.0/ref/settings/#databases
    
    DATABASES = {
         'default':{
             'NAME': 'venn',
             'ENGINE': 'sql_server.pyodbc',
             'HOST': '127.0.0.1',
             'PORT': '1433',
             'USER': 'venndata',
             'PASSWORD': 'venndata',
             'OPTIONS':{
                 'driver':'SQL Server Native Client 10.0',
             }
         },
         'venn': {
             'NAME': 'venn',
             'ENGINE': 'sql_server.pyodbc',
             'HOST': '127.0.0.1',
             'PORT': '1433',
             'USER': 'venndata',
             'PASSWORD': 'venndata',
             'OPTIONS':{
                 'driver':'SQL Server Native Client 10.0',
             }
         },
         'vip_cluster': {
             'NAME': 'vip_cluster',
             'ENGINE': 'sql_server.pyodbc',
             'HOST': '127.0.0.1',
             'PORT': '1433',
             'USER': 'venndata',
             'PASSWORD': 'venndata',
             'OPTIONS':{
                 'driver':'SQL Server Native Client 10.0',
             }
         },
         'catecheck': {
             'NAME': 'catecheck',
             'ENGINE': 'sql_server.pyodbc',
             'HOST': '127.0.0.1',
             'PORT': '1433',
             'USER': 'venndata',
             'PASSWORD': 'venndata',
             'OPTIONS':{
                 'driver':'SQL Server Native Client 10.0',
             }
         },
         'skucheck': {
             'NAME': 'skucheck',
             'ENGINE': 'sql_server.pyodbc',
             'HOST': '127.0.0.1',
             'PORT': '1433',
             'USER': 'venndata',
             'PASSWORD': 'venndata',
             'OPTIONS':{
                 'driver':'SQL Server Native Client 10.0',
             }
         },
          'barcode': {
             'NAME': 'barcode',
             'ENGINE': 'sql_server.pyodbc',
             'HOST': '127.0.0.1',
             'PORT': '1433',
             'USER': 'venndata',
             'PASSWORD': 'venndata',
             'OPTIONS':{
                 'driver':'SQL Server Native Client 10.0',
             }
         }
     }
    
    
    DATABASE_ROUTERS = ['vennsystem.database_router.DatabaseAppsRouter']
    
    
    DATABASE_APPS_MAPPING = {
         # example:
         # 'app_name':'database_name',
         'venncheck': 'skucheck',
         'barcode': 'barcode',
         'catecheck': 'catecheck',
         'clust': 'vip_cluster',
         'the_entrance': 'venn',
         'admin': 'venn',
         'auth': 'venn',
         'contenttypes': 'venn',
         'sessions': 'venn',
    }

     

    DATABASES大家都知道,是配置数据库连接的(这里要注意的是我用的是sql server数据库,里面OPTIONS是非常重要的参数,一定要把这个加进去,不然跑不起来)。default是默认的数据库,在这里可以为{},但是一旦为空不可以执行'python manage.py migrate'(会在下个部分说怎么处理)

      之后是DATABASE_ROUTERS这个指向的是我们自己写的那个类(['项目名.文件名.类名'])。最后是路由分配,把app的名字和数据库对应起来。 

      在模型中的部分特别简单,只要加两行代码就可以解决:

     

    class Href(models.Model):
         name = models.CharField(max_length=100)
         path = models.CharField(max_length=100)
     
         class Meta:
             app_label = 'the_entrance'

     

    三、执行

      执行的顺序就是大家熟悉的了:

      1.python manage.py makemigrations

      之后的稍有不同:

      2.python manage.py migrate --database=skucheck

         python manage.py migrate --database=barcode

         ......

         python manage.py migrate(只有默认数据库不为空时才可以这么实用,若为空则是用上面的方法)

         其实在这里没有特别的执行顺序,但是我个人建议大家是最后执行migrate(即默认数据库)。另外要注意一点,admin、auth、contenttypes和sessions是一定要在一个app里被makemigrations放到一个XXXX_initial.py文件中的,不然你怎么migrate都不会有这些Django自建的表的!


     

    ***最后的最后一定要注意:不在一个库里了,没法跨库建立约束关系,放弃外键,老老实实一步步查!****

     

     

     

     

  • 相关阅读:
    常用知识点集合
    LeetCode 66 Plus One
    LeetCode 88 Merge Sorted Array
    LeetCode 27 Remove Element
    LeetCode 26 Remove Duplicates from Sorted Array
    LeetCode 448 Find All Numbers Disappeared in an Array
    LeetCode 219 Contains Duplicate II
    LeetCode 118 Pascal's Triangle
    LeetCode 119 Pascal's Triangle II
    LeetCode 1 Two Sum
  • 原文地址:https://www.cnblogs.com/wtil/p/9529315.html
Copyright © 2011-2022 走看看