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

    一、定义数据库

    使用Django的多个数据库的第一步是告诉Django将使用的数据库服务器。 这是使用DATABASES设置完成的。 此设置将数据库别名映射到该特定连接的设置字典,该数据库别名是一种在整个Django中引用特定数据库的方法。 内部词典中的设置在DATABASES文档中有完整描述。

    数据库可以包含您选择的任何别名。 当没有选择其他数据库时,Django使用具有默认别名default的数据库。

    需求分析:

    • 在进行django项目开发的时候,遇到了需要连接两个MySQL数据库的问题。同时使用django自带的admin进行后台数据管理。针对django项目中有多个app,app之间使用不同数据库的需求。

    下面是 settings.py 中的DATABASES配置:

    DATABASES = {
     'default': {   
     # 'ENGINE': 'django.db.backends.sqlite3',                #没有指定使用数据库的话就是使用default中的数据库
     # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),           
     },
     'db_a': {
     'ENGINE': 'django.db.backends.mysql',
     'NAME': 'student',
     'USER': 'root',
     'PASSWORD': '123',
     "HOST": "localhost",
     "PORT": '3306',
     },
     'db_b': {
     'ENGINE': 'django.db.backends.mysql',
     'NAME': 'teacher',
     'USER': 'root',
     'PASSWORD': '123',
     "HOST": "localhost",
     "PORT": '3306',
     },
    

    其中default可以为空,但是不能删除,db_a, db_b是需要配置的数据库连接信息。

    二、设置路由,将app映射到相对应的数据库

    创建一个database_router.py文件,添加内容如下:

    # -*- coding: utf-8 -*-
    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
    
    	# for Django 1.4 - Django 1.6
    	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
    
    	# Django 1.7 - Django 1.11
    	def allow_migrate(self, db, app_label, model_name=None, **hints):
    		# print db, app_label, model_name, hints
    		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中添加路由:

    # 数据库路由
    DATABASE_ROUTERS = ['project_name.database_router.DatabaseAppsRouter']     # 路径
    
    # 根据app名称路由指定的数据库
    DATABASE_APPS_MAPPING = {
     'app01': 'db_a',
     'app02': 'db_b',
    } 
    

    四、为每个app的model分别指定所需要连接的数据库

    class UserProfile(models.Model):
        username=models.CharField(max_length=32)
        password=models.CharField(max_length=64)
    
    
        def __str__(self):
            return self.name
    
        class Meta:
            app_label = 'app01'     #定义该model的app_label
    

    此时实现了不同app 使用对应的数据库了, 当然也可以多个sqlite3和MySQL一起使用,甚至可以为每个app单独设置一个数据库。不设置或者没有设置的app会使用默认的数据库。

    之后模型修改迁移的时候可以通过--database指定迁移使用的数据库

    python manage.py makemigrations
    python manage.py migrate --database=db_a
    

    需求二:

    • 对于一个app里想要使用不同数据库进行查询增删等,可以通过指定数据库的方式进行,使用using()方法。

    如:

    task = User.objects.using('db_a').filter(userId = 1)[0]
     

     

    使用Django中的admin操作指定的数据库

    在admin.py中通过下述代码告诉django在处理这些model的orm关系时,使用settings里配置的哪个数据库进行连接。然后再与正常一样进行使用。

    class MultiDBModelAdmin(admin.ModelAdmin):
        # A handy constant for the name of the alternate database.
        using = 'db_a' #指定使用的数据库
    
        def save_model(self, request, obj, form, change):
            # Tell Django to save objects to the 'other' database.
            obj.save(using=self.using)
    
        def delete_model(self, request, obj):
            # Tell Django to delete objects from the 'other' database
            obj.delete(using=self.using)
    
        def get_queryset(self, request):
            # Tell Django to look for objects on the 'other' database.
            return super(MultiDBModelAdmin, self).get_queryset(request).using(self.using)
    
        def formfield_for_foreignkey(self, db_field, request, **kwargs):
            # Tell Django to populate ForeignKey widgets using a query
            # on the 'other' database.
            return super(MultiDBModelAdmin, self).formfield_for_foreignkey(db_field, request, using=self.using, **kwargs)
    
        def formfield_for_manytomany(self, db_field, request, **kwargs):
            # Tell Django to populate ManyToMany widgets using a query
            # on the 'other' database.
            return super(MultiDBModelAdmin, self).formfield_for_manytomany(db_field, request, using=self.using, **kwargs)
    
    
    class UserProfileAdmin(MultiDBModelAdmin):
        model = CraCrawl
    
    
    admin.site.register(UserProfile, UserProfileAdmin)    #注册模型到admin后台管理页面
    

    这样就能在admin中管理指定的数据库了。

    参考链接:

  • 相关阅读:
    python基础知识的重点面试题
    初入SG-UAP
    sg-uap常用注解介绍
    Git简介
    Docker 阿里云镜像加速
    Elasticsearch 读时分词、写时分词
    Java 显示调用隐式调用
    SecureFX中文目录乱码问题解决方案
    Linux 防火墙遇到的问题
    Docker Gitlib创建项目后仓库连接IP地址不一致问题(包括进入docker中容器命令及退出命令)
  • 原文地址:https://www.cnblogs.com/ray-h/p/10747872.html
Copyright © 2011-2022 走看看