zoukankan      html  css  js  c++  java
  • django 项目中使用多数据库 multiple databases

    假如在一个django项目中使用到了不只一个数据库, 其实这在大一点的工程中很常见,比如主从库

    那么会涉及到如下一些东西

    1, 定义

    在settings中的DATABASE中定义会使用到的数据,比如除default外我们还定义了一个 search

     1 DATABASE = {
     2     'default':{
     3         'ENGINE': 'django.db.backends.sqlite3',
     4         'NAME': 'path/to/database.sqllite3',
     5         'USER':'',
     6         'PASSWORD':'',
     7         'HOST': '',
     8         'PORT':'',
     9     },
    10     'search':{
    11         'ENGINE': 'django.db.backends.mysql',
    12         'NAME': 'search_db',
    13         'USER':'db_user',
    14         'PASSWORD':'p@55word',
    15         'HOST': '192.168.12.186',
    16         'PORT':'',
    17     }  
    18 } 

    2, 使用

    会产生数据库操作的几个地方

    • Model对象
    • QuerySet
    • manager

    假如有Model对象 obj

    它的save()会执行  INSERT 或  UPDATE

    它的 delete() 会执行  DELETE

    我们拿到一个obj,或者创建一个新的obj后,使用非default db时,  参数中传进using

    obj = Person(name='wy', uid=530)
    obj.save(using='search')
    obj.delete(using='search')

    通过manager拿到的都是QuerySet, 它对应数据库中的一个集合, 对应的语句是 SELECT

    QuerySet有using方法, 指定去SELECT的数据库, 而QuerySet有一组方法是返回QuerySet对象的,所以只要在这个调用链中使用 using 就行

    Person.objects.all().using('search').filter(uid__gt=100)

    而manager本身提供了一个方法using, 这么定义的

    def using(self, *args, **kwargs):
        return self.get_queryset().using(*args, **kwargs)

    所以上面那行代码等效于

    Person.objects.using('search').filter(uid__gt=100)

    有时候我们会在manager层面设置使用的数据库. 比如对自定义的manager.

    自定义的manager常见的一个情况是重写get_queryset()方法, 比如一个lady_manager,它可以重写get_queryset()只返回所有lady,然后再在这个基础上filter...

    其实manager返回的QuerySet的_db是manager自己的_db传过去的, 而manager有 db_manager()这个方法来设置自身的_db

    def db_manager(self, using):    
        obj = copy.copy(self)
        obj._db = using
        return obj

    所以只要这么用就好, 假如Person有一个自定义manager   ladies

    Person.ladies.db_manager('search').all()

     3, admin使用多数据库

    admin是django自带的一个app,那它涉及的是,读一个Model的所有对象(读一张表SELECT), 增加,删除,那么重写admin.ModelAdmin的如下几个做这几件事方法就好了

    class MultiDBModelAdmin(admin.ModelAdmin):
        # A handy constant for the name of the alternate database.
        using = 'other'
    
        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=None, **kwargs):
            # Tell Django to populate ForeignKey widgets using a query
            # on the 'other' database.
            return super(MultiDBModelAdmin, self).formfield_for_foreignkey(db_field, request=request, using=self.using, **kwargs)
    
        def formfield_for_manytomany(self, db_field, request=None, **kwargs):
            # Tell Django to populate ManyToMany widgets using a query
            # on the 'other' database.
            return super(MultiDBModelAdmin, self).formfield_for_manytomany(db_field, request=request, using=self.using, **kwargs)

    如上代码摘自django文档,关于 formfield_for_foreignkey 和  formfield_for_manytomany 还没细研究

    把上面的类定义放到自己的代码中,然后自己的ModelAdmin从它派生就行了, using中指定要使用的数据库, 如

    class PersonAdmin(MultiDBAdmin):
        pass
    admin.site.register(PersonAdmin, Person)

    -----------------------

    参考:

    https://docs.djangoproject.com/en/1.6/topics/db/multi-db/

  • 相关阅读:
    格式化时间
    鼠标经过,图片放大事件
    reboot 后 Docker服务及容器自动启动设置
    gin 单个文件函数 上传文件到本地目录里
    深度Linux deepin更新,防火墙操作
    第四篇 mybatis的运行原理(1):重要组件的介绍
    第三篇 常用配置和动态SQL
    第二篇 mybatis的入门
    记一次强转bug
    第一篇 mybatis的简介
  • 原文地址:https://www.cnblogs.com/livingintruth/p/3760958.html
Copyright © 2011-2022 走看看