Django模型-数据库配置

上一章介绍了Django model的一些基本理念,接下来让我们开始Django数据库层的探索。首先,我们需要做些初始配置;我们需要告诉Django使用什么数据库以及如何连接数据库。

Django 对各种数据库提供了很好的支持,包括:PostgreSQL、MySQL、SQLite、Oracle。

Django 为这些数据库提供了统一的调用API。 我们可以根据自己业务需求选择不同的数据库。

备注:本章不介绍相关数据库在服务器上的安装及激活等。我们假定你已经完成了数据库服务器的安装和激活,并且在其中创建了数据库(例如,用CREATE DATABASE语句)。如果你使用SQLite,则不需要这不安装,因为SQLite使用文件系统上的独立文件来存储数据。

SQLite

SQLite是Django默认的数据库,当我们创建一个Django项目后,配置文件里就已经帮我们配置好了SQLite。

#settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

当我们使用python manage.py makemigrations python manage.py migrate myapp应用数据库后,会在项目目录下看到db.sqlite3,这就是项目的SQLite数据库文件,可使用sqlite3连接使用。

➜  myproject ls
db.sqlite3 manage.py  myapp      myproject
➜  myproject sqlite3 db.sqlite3
SQLite version 3.19.3 2017-06-27 16:48:08
Enter ".help" for usage hints.
sqlite>

MySQL

数据库切换成Mysql需要我们对配置进行修改

#settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'myproject', #数据库名字,
        'USER': 'root', #数据库登录用户名
        'PASSWORD': '123456', #数据库登录密码
        'HOST': 'localhost', #数据库所在主机(项目中写真实主机地址)
        'PORT': '3306', #数据库端口
    }
}

python2中,使用pip install mysql-python 进行安装连接MySQL的库,使用时 import MySQLdb 进行使用.

python3中,改变了连接库,改为了pymysql库,使用pip install pymysql进行安装,直接导入即可使用

但是在Django中, 连接数据库时使用的是MySQLdb库,这在与python3的合作中就会报以下错误了:

django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named 'MySQLdb'

解决办法:找到项目配置目录下的init.py

➜  myproject ls
db.sqlite3 manage.py  myapp      myproject
➜  myproject vim myproject/__init__.py

添加以下代码:

import pymysql
pymysql.install_as_MySQLdb()

当然,首先你得安装这个模块,pip install pymysql。。。

Oracle

数据库切换成Oracle需要我们对配置进行修改

#settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.oracle',
        'NAME': 'myproject', #数据库名字,
        'USER': 'root', #数据库登录用户名
        'PASSWORD': '123456', #数据库登录密码
        'HOST': 'localhost', #数据库所在主机(项目中写真实主机地址)
        'PORT': '3306', #数据库端口
    }
}

如果使用Oracle,需要安装cx_Oracle库,可以从https://pypi.python.org/pypi/cx_Oracle/获得。 要用4.3.1或更高版本,但要避开5.0,这是因为这个版本的驱动有bug。

PostgreSQL

数据库切换成PostgreSQL需要我们对配置进行修改

#settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'myproject', #数据库名字,
        'USER': 'root', #数据库登录用户名
        'PASSWORD': '123456', #数据库登录密码
        'HOST': 'localhost', #数据库所在主机(项目中写真实主机地址)
        'PORT': '3306', #数据库端口
    }
}

安装第三方库: pip install psycopg2

数据库配置错误信息

错误信息 解决办法
You haven’t set the DATABASE_ENGINE setting yet. 不要以空字符串配置DATABASE_ENGINE 的值。 表格 5-1 列出可用的值。
Environment variable DJANGO_SETTINGS_MODULE is undefined. 使用python manager.py shell 命令启动交互解释器,不要以python 命令直接启动交互解释器。
Error loading _ module: No module named _. 未安装合适的数据库适配器 (例如, psycopg 或 MySQLdb )。Django并不自带适配器,所以你得自己下载安装。
_ isn’t an available database backend. 把DATABASE_ENGINE 配置成前面提到的合法的数据库引擎。 也许是拼写错误?
database _ does not exist 设置DATABASE_NAME 指向存在的数据库,或者先在数据库客户端中执行合适的CREATE DATABASE 语句创建数据库。
role _ does not exist 设置DATABASE_USER 指向存在的用户,或者先在数据库客户端中执创建用户。
could not connect to server 查看DATABASE_HOST和DATABASE_PORT是否已正确配置,并确认数据库服务器是否已正常运行。

MongoDB

上述都是Django默认支持的关系型数据库,对于非关系型的数据库,例如MongoDB,是不支持的。不支持不代表不能用,只是如果在Django中使用MongoDB,需要自己动手写相应的扩展。

适配器

选择pymongo作为我们MongoDB的适配器

pip install pymongo

数据库配置

#settings.py
MONGODB_CONFIG = {
    'host': '127.0.0.1',
    'port': 27017,
    'db_name': 'test',
    'username': None,
    'password': None
}

自定义数据连接

#connection.py
import pymongo
import sys
import traceback
from settings import MONGODB_CONFIG

class Singleton(object):
    '''单例模式'''
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            orig = super(Singleton, cls)
            cls._instance = orig.__new__(cls, *args, **kwargs)
        return cls._instance

class MongoConn(Singleton):
    '''单例并连接mongodb'''
    def __init__(self):
        try:
            self.conn = pymongo.MongoClient(MONGODB_CONFIG['host'], MONGODB_CONFIG['port'])
            self.db = self.conn[MONGODB_CONFIG['db_name']]  # connect db
            self.username=MONGODB_CONFIG['username']
            self.password=MONGODB_CONFIG['password']
            if self.username and self.password:
                self.connected = self.db.authenticate(self.username, self.password)
            else:
                self.connected = True
        except Exception:
            print(traceback.format_exc())
            print('Connect Statics Database Fail.')
            sys.exit(1)

自定义数据操作api

#api.py
import traceback
import logging
from connection import MongoConn

LOGGER = logging.getLogger("mongodb") # 为loggers中定义的名称

def check_connected(conn):
    '''检查是否连接成功'''
    if not conn.connected:
        raise NameError('stat:connected Error')

def save(table, value):
    '''一次操作一条记录,根据‘_id’是否存在,决定插入或更新记录'''
    try:
        my_conn = MongoConn()
        check_connected(my_conn)
        my_conn.db[table].save(value)
    except Exception:
        LOGGER.error(traceback.format_exc())

def del_one(table, value):
    '''
    删除指定记录
    '''
    try:
        my_conn = MongoConn()
        check_connected(my_conn)
        my_conn.db[table].delete_one(value)
    except Exception:
        LOGGER.error(traceback.format_exc())

def del_all(table, value):
    '''
    删除所有匹配的记录
    返回了一个DeleteResult对象。这个对象报告了被删除的文档数目。
    要查看被删除的文档数目,通过访问DeleteResult对象的deleted_count属性
    '''
    try:
        my_conn = MongoConn()
        check_connected(my_conn)
        result = my_conn.db[table].delete_many(value)
    except Exception:
        LOGGER.error(traceback.format_exc())
    return result

def insert(table, value):
    # 可以使用insert直接一次性向mongoDB插入整个列表,也可以插入单条记录,但是'_id'重复会报错
    try:
        my_conn = MongoConn()
        check_connected(my_conn)
        my_conn.db[table].insert(value, continue_on_error=True)
    except Exception:
        LOGGER.error(traceback.format_exc())

def update(table, conditions, value, s_upsert=False, s_multi=False):
    '''
    condition: update的查询条件
    value: update的对象和一些更新的操作符(如$,$inc...)等
    upsert : 如果不存在update的记录,是否插入记录.默认是false,不插入。
    multi : 默认是false,只更新找到的第一条记录.若为true,
        就把按条件查出来多条记录全部更新。
    '''
    try:
        my_conn = MongoConn()
        check_connected(my_conn)
        my_conn.db[table].update(conditions, value, upsert=s_upsert, multi=s_multi)
    except Exception:
        LOGGER.error(traceback.format_exc())

def upsert_mary(table, datas):
    '''
    批量更新插入,根据‘_id’更新或插入多条记录。
    把'_id'值不存在的记录,插入数据库。'_id'值存在,则更新记录。
    如果更新的字段在mongo中不存在,则直接新增一个字段
    '''
    try:
        my_conn = MongoConn()
        check_connected(my_conn)
        bulk = my_conn.db[table].initialize_ordered_bulk_op()
        for data in datas:
            _id = data['_id']
            bulk.find({'_id': _id}).upsert().update({'$set': data})
        bulk.execute()
    except Exception:
        LOGGER.error(traceback.format_exc())

def upsert_one(table, data):
    '''
    更新插入,根据‘_id’更新一条记录,如果‘_id’的值不存在,则插入一条记录
    '''
    try:
        my_conn = MongoConn()
        check_connected(my_conn)
        query = {'_id': data.get('_id', '')}
        if not my_conn.db[table].find_one(query):
            my_conn.db[table].insert(data)
        else:
            data.pop('_id') #删除'_id'键
            my_conn.db[table].update(query, {'$set': data})
    except Exception:
        LOGGER.error(traceback.format_exc())

def find_one(table, value):
    '''
    根据条件进行查询,返回一条记录
    '''
    try:
        my_conn = MongoConn()
        check_connected(my_conn)
        return my_conn.db[table].find_one(value)
    except Exception:
        LOGGER.error(traceback.format_exc())

def find(table, value=None):
    '''
    根据条件进行查询,返回所有记录
    当value为None时,默认返回table里所有记录
    '''
    try:
        my_conn = MongoConn()
        check_connected(my_conn)
        return my_conn.db[table].find(value)
    except Exception:
        LOGGER.error(traceback.format_exc())

def select_colum(table, value, colum):
    '''
    查询指定列的所有值
    '''
    try:
        my_conn = MongoConn()
        check_connected(my_conn)
        return my_conn.db[table].find(value, {colum:1})
    except Exception:
        LOGGER.error(traceback.format_exc())

def insert_infographic_block(mongdb_id,page_id,block):
    '''
    插入一个infographic
    '''
    try:
        my_conn = MongoConn()
        check_connected(my_conn)
        operation =  {colum: 1}

        return my_conn.db["infographic"].find({'_id': mongdb_id},)
    except Exception:
        LOGGER.error(traceback.format_exc())

测试使用

请确认MongoDB数据库已在服务器正常启动

(.venv) ➜  myproject ✗ python manage.py shell
Python 3.6.4 (v3.6.4:d48ecebad5, Dec 18 2017, 21:07:28)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from api import save as mongdb_save, find_one as mongdb_find, del_one as mongdb_delete
>>> test = {'test': 'this is just a test'}
>>> mongdb_save('test', test)

>>> result = mongdb_find('test', {'test': 'this is just a test'})
>>> result
{'_id': ObjectId('5b602baaf8aff5dd0b1dfab7'), 'test': 'this is just a test'}

>>> mongdb_delete('test', {'test': 'this is just a test'})

>>> result = mongdb_find('test', {'test': 'this is just a test'})
>>> result
>>>
Copyright © itrunner.cn 2020 all right reserved,powered by Gitbook该文章修订时间: 2022-08-28 07:44:16

results matching ""

    No results matching ""