Django: 之数据库导入、迁移和联用
Django 数据库导入
从网上下载的一些数据,excel表格,xml文件,txt文件等有时候我们想把它导入数据库,应该如何操作呢?
以下操作符合 Django版本为 1.6 ,兼顾 Django 1.7, Django 1.8 版本,理论上Django 1.4, 1.5 也没有问题,没有提到的都是默认值
备注:你可能会问数据从哪儿来的,比如你用python从以前的blog上获取过来的,想导入现在的博客,或者别人整理好的数据,或者你自己整理的excel表,一个个地在网站后台复制粘贴你觉得好么?这就是批量导入的必要性。
建议先不要看源码,按教程一步步做下去,遇到问题再试试源代码,直接复制粘贴,很快就会忘掉,自己动手打一遍
我们新建一个项目mysite,在新建一个app,名称为blog
django-admin.py startproject mysite
cd mysite
python manage.py startapp blog
把blog中的models.py更改为一下内容
#!/usr/bin/python
#coding:utf-8 from django.db import models class Blog(models.Model):
title = models.CharField(max_length=100)
content = models.TextField() def __unicode__(self):
return self.title
不要忘了把blog加入到settings.py中的INSTALLED_APPS中。
# Application definition
INSTALLED_APPS = (
... # 添加上 blog 这个 app
'blog',
)
一、同步数据库,创建相应的表
python manage.py syncdb
Django 1.6以下版本会看到:

Django创建了一些默认的表,注意后面哪个红色标记的blog_blog是appname_classname的样式,这个表是我们自己写的Blog类创建的
Django 1.7.6及以上的版本会看到:(第六行即创建了对应的blog_blog表)
Operations to perform:
Synchronize unmigrated apps: blog
Apply all migrations: admin, contenttypes, auth, sessions
Synchronizing apps without migrations:
Creating tables...
Creating table blog_blog
Installing custom SQL...
Installing indexes...
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying sessions.0001_initial... OK You have installed Django's auth system, and don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (leave blank to use 'tu'): wulaoer
Email address:
Password:
Password (again):
Superuser created successfully.
二、输入python manage.py shell
进入该项目的django环境的终端(windows如何进入对应目录?看Django环境搭建的3.2部分)
先说说如何使用命令新增一篇文章:
$ python manage.py shell
>>> from blog.models import Blog
>>> Blog.objects.create(title="The first blog of my site",
content="I am writing my blog on Terminal")
这样就新增了一篇博文,我们查看以下
>>> Blog.objects.all() # 获取所有blog
[<Blog: The first blog of my site>]
还有两种方法(这两种差不多):
>>> blog2 = Blog()
>>> blog2.title = "title 2"
>>> blog2.content = "content 2"
>>> blog2.save()
或者
>>> blog2 = Blog(title="title 2",content="content 2")
>>> blog2.save()
后面两种方法也很重要,尤其是用在修改数据的时候,要记得最后要保存以下blog.save(),第一种Blog.objects.create()是自动保存的。
三、批量导入
比如我们要导入一个文本,里面是标题和内容,中间用四个*隔开的,示例(pldblog.txt):
title 1****content 1
title 2****content 2
title 3****content 3
title 4****content 4
title 5****content 5
title 6****content 6
title 7****content 7
title 8****content 8
title 9****content 9
在终端导入有时候有些不方便,我们在最外面哪个mysite目录下写个脚本,叫txt2db.py,把lodblog.txt也放在mysite下
#!/usr/bin/env python
#coding:utf-8 import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") '''
Django 版本大于等于1.7的时候,需要加上下面两句
import django
django.setup()
否则会抛出错误 django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.
''' import django
if django.VERSION >= (1, 7):#自动判断版本
django.setup() def main():
from blog.models import Blog
f = open('oldblog.txt')
for line in f:
title,content = line.split('****')
Blog.objects.create(title=title,content=content)
f.close() if __name__ == "__main__":
main()
print('Done!')
好了,我们在终端运行它
python txt2db.py
# 运行完后显示 一个 Done! 导入完成!
四、导入数据重复解决办法
如果你导入数据过多,导入时出错了,或者你手动停止了,导入了一部分,还有一部分没有导入。或者你再次运行上面的命令,你会发现数据重复了,怎么办呢?
django.db.models中还有一个函数叫get_or_create()有就获取过来,没有就创建,用它可以避免重复,但是速度可以会慢些,因为要先尝试获取,看看有没有
只要把上面的
Blog.objects.create(title=title,content=content)
换成下面的就不会重复导入数据了
Blog.objects.get_or_create(title=title,content=content)
返回值是(BlogObject,True/False)新建时返回True,已经存在时返回False。
更多数据库API的知识请参见官网文档:QuerySet API
五、用fixture导入
最常见的fixture文件就是python manage.py dumpdata导出的文件,示例如下:
[
{
"model": "myapp.person",
"pk": 1,
"fields": {
"first_name": "John",
"last_name": "Lennon"
}
},
{
"model": "myapp.person",
"pk": 2,
"fields": {
"first_name": "Paul",
"last_name": "McCartney"
}
}]
你也可以根据自己的models,创建这样的json文件,然后用python manage.py loaddata fixture.json导入
详见:https://docs.djangoproject.com/en/dev/howto/initial-data/
可以写一个脚本,把要导入的数据转换成json文件,这样导入也会更快些!
六、Model.objects.bulk_create()更快更方便
#!/usr/bin/env python
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") def main():
from blog.models import Blog
f = open('oldblog.txt')
BlogList = []
for line in f:
title,content = line.split('****')
blog = Blog(title=title,content=content)
BlogList.append(blog)
f.close() Blog.objects.bulk_create(BlogList) if __name__ == "__main__":
main()
print('Done!')
由于Blog.objects.create()每保存一条就执行一次SQL,而bulk_create()是执行一条SQL存入多条数据,做会块很多!当然用列表解析代替for循环会更快!!
#!/usr/bin/env python
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") def main():
from blog.models import Blog
f = open('oldblog.txt') BlogList = []
for line in f:
parts = line.split('****')
BlogList.append(Blog(title=parts[0], content=parts[1])) # 以上四行 也可以用 列表解析 写成下面这样
# BlogList = [Blog(title=line.split('****')[0], content=line.split('****')[1]) for line in f] Blog.objects.bulk_create(BlogList) if __name__ == "__main__":
main()
print('Done!')
当然也可以利用数据中的导出,在导入的方法,
Django 数据迁移
Django数据库不同数据库,SQLite3,MySQL,PostgreSQL之间数据迁移的方案,以及不同机器之间的迁移方案
一、简单的数据导出与导入(简单的迁移)
1、django项目提供了一个导出的方法python manage.py dumpdata,不指定appname时默认为导出所有的app
python manage.py dumpdata [appname] > appname_data.json
比如我们有一个项目叫mysite,里面有一个app叫blog,我们想导出blog的所有数据
python manage.py dumpdata blog > blog_dump.json
2、数据导入,不需要指定appname
python manage.py loaddata blog_dump.json
备注:一些常用的
python manage.py dumpdata auth > auth.json # 导出用户数据
优点:可以兼容各种支持的数据库,也就是说,以前用的是SQLite3,可以导出后,用这种方法导入到MySQL,PostgreSQL等数据库,反过来也可以。
缺点:数据量大的时候,速度相对较慢,表的关系比较复杂的时候可以导入不成功。
二、数据库的迁移
2、1用Django自带的命令
比如早期我们为了开发方便,用sqlite3数据库,后来发现网站数据太多,sqlite3性能有点跟不上了,想换成postgreSQL或者MySQL的时候。
如果我还使用上面的命令,如果你运气好的话,也许会导入成功,流程如下:
2.1.1 从原来的整个数据库导出所有数据
python manage.py dumpdata > mysite_all_data.json
2.1.2 将mysite_all_data.json传送到另一个服务器或者电脑上导入
python manage.py loaddata mysite_all_data.json
如果你运气好的话可能会导入完成,但是往往不那么顺利,原因如下:
a)我们在写models的时候如果用到CharField,就一定要写max_length,在sqlite3中是不检查这个最大长度的,你写最大运行长度为100.你网数据库放10000个,sqlite3都不报错,而且不截断数据的长度,这似乎是slite3的优点,但是也给从sqlite3导入其他数据库带来了困难,因为MySQL和PostgreSQL数据库都会检查最大长度,超出时就报错!
b)Django自带的contentType会导致出现一些问题
用上面的方法只迁移一个app应该问题不大,但是如果有用户,用户组挂钩,事情往往变得糟糕!如果导入后没有对数据进行修改,你可以重新导入,可能还要块一些,如果是手动在后人输入或者修改过,这种方法就不适用了
2.2、用数据库自带的导出导入命令
假定Django用的数据库名称为wulaoer
2.2.1 在PostgreSQL中:
# 导出数据库 zqxt 到 wulaoer.sql 文件中
pg_dump wulaoer > wulaoer.sql # 导入数据库到 新的服务器
psql wulaoer -f wulaoer.sql #注意:数据导入导出可能需要数据库超级权限,用 sudo su postgres 切换到数据库超级用户 postgres
2.2.2 在MySQL中:
使用网页工具,比如phpMyAdmin导入导出很简单,这里就不说了,主要就说一下命令行如何操作:
# 导出数据库 wulaoer 到 wulaoer.sql 文件中
mysqldump -u username -p --database wulaoer > wulaoer.sql # 导入数据库到 新的服务器
mysql -u username -p
输入密码进入 MySQL 命令行
> source /path/to/wulaoer.sql
总结:其他的数据库,请自行搜索如何导入导出,整个数据库导出的好处就是对数据之间的关系处理比较省事,比如自强学堂里面的很多教程,上篇和下一篇是一个一对一的关系,这样的话用python manage.py dumpdata无法导出教程与教程的关系,但是数据库整个导出就没有任何问题,当然也可以写一个脚本导出关系再导入。Django自带的python manage.py dumpdata和python manage.py loaddata最大的好处就是可以跨站数据库进行导入导出。
Django 多数据库联用
以下是讲述在一个django project中使用多个数据库的方法,多个数据库的联用以及多数据库时数据库导入导出的方法。
直接给出一种简单的方法,想了解更多可以到官方,点击此处
代码文件下载:
1、每个app都可以单独设置一个数据库
settings.py中有数据库的相关设置,有一个默认的数据库default,我们可以再加一些其他的,比如:
# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
'db1': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'dbname1',
'USER': 'your_db_user_name',
'PASSWORD': 'yourpassword',
"HOST": "localhost",
},
'db2': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'dbname2',
'USER': 'your_db_user_name',
'PASSWORD': 'yourpassword',
"HOST": "localhost",
},
} # use multi-database in django
# add by WeizhongTu
DATABASE_ROUTERS = ['project_name.database_router.DatabaseAppsRouter']
DATABASE_APPS_MAPPING = {
# example:
#'app_name':'database_name',
'app1': 'db1',
'app2': 'db2',
}
在project_name文件夹中存放database_route.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 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
这样就实现了指定的app使用指定的数据库了,当然你也可以多个sqlite3一起使用,相当于可以给每个app都可以单独设置一个数据库!如果不设置或者有设置的app就会自动使用默认的数据库
2、多个数据库联用时数据库导入导出
使用的时候和一个数据库的区别是:
如果不是defalut(默认数据库)要在命令后加--database=数据库对应的settings.py中的名称 如: --database=db1 或 --database=db2
数据库同步(创建表)
python manage.py syncdb #同步默认的数据库,和原来的没有区别 #同步数据库 db1 (注意:不是数据库名是db1,是settings.py中的那个db1,不过你可以使这两个名称相同,容易使用)
python manage.py syncdb --database=db1
数据导出
python manage.py dumpdata app1 --database=db1 > app1_fixture.json
python manage.py dumpdata app2 --database=db2 > app2_fixture.json
python manage.py dumpdata auth > auth_fixture.json
数据导入
python manage.py loaddata app1_fixture.json --database=db1
python manage.py loaddata app2_fixture.json --database=db2
Django: 之数据库导入、迁移和联用的更多相关文章
- Django更换数据库和迁移数据方案
前言 双十一光顾着买东西都没怎么写文章,现在笔记里还有十几篇半成品文章没写完- 今天来分享一下 Django 项目切换数据库和迁移数据的方案,网络上找到的文章方法不一,且使用中容易遇到各类报错,本文根 ...
- Python第十三天 django 1.6 导入模板 定义数据模型 访问数据库 GET和POST方法 SimpleCMDB项目 urllib模块 urllib2模块 httplib模块 django和web服务器整合 wsgi模块 gunicorn模块
Python第十三天 django 1.6 导入模板 定义数据模型 访问数据库 GET和POST方法 SimpleCMDB项目 urllib模块 urllib2模块 ...
- Django import / export实现数据库导入导出
使用django-import-export库,导入导出数据,支持csv.xls.json.html等格式 官网:http://django-import-export.readthedocs.io/ ...
- django中数据库的配置及相关增删改查
ORM ORM是什么?:(在django中,根据代码中的类自动生成数据库的表也叫--code first) ORM:Object Relational Mapping(关系对象映射) 类名对应---- ...
- python3之Django多数据库
1.定义数据库 在django项目中, 一个工程中存在多个APP应用很常见:有时候希望不同的APP连接不同的数据库,这个时候需要建立多个数据库连接.在Django的setting中使用DATABASE ...
- django 操作数据库--orm(object relation mapping)---models
思想 django为使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM). PHP:activerecord Java:Hibernate C#:Ent ...
- Access数据库导入到SQL Server 2005 Express中
安装好SQL Server 2005 Express后,再安装SQL Server Management Studio Express CTP就可以很方便的使用控制台进行数据库的管理.但SQL Ser ...
- mysql数据库导入外键约束问题
在网站搬迁过程中,很重要一点是数据的迁移.你的数据库可能已经包含了一个设计良好的数据表集合,并且在网站运营过程中,产生了重要的数据.这时你必须做好包含数据表schema以及数据本身的迁移. 完成上述数 ...
- Django模型-数据库操作
前言 前边记录的URLconf和Django模板全都是介绍页面展示的东西,也就是表现层的内容.由于Python先天具备简单而强大的数据库查询执行方法,Django 非常适合开发数据库驱动网站. 这篇开 ...
随机推荐
- linux命令英文缩写的含义(方便记忆)
命令缩写: ls:list(列出目录内容) cd:Change Directory(改变目录) su:switch user 切换用户 rpm:redhat package manager 红帽子打包 ...
- 一些常用数据库操作在mysql及sql server中实现方式的差异
因为本文强调的是不同点,所以先讲述不同点,再讲相同点. 一.不同点 1.创建表时主键id的自增实现方式不一样 mysql数据库的实现方式是auto_increment,示例如下 CREATE TABL ...
- ios文本框基本使用,以及所有代理方法的作用
/* UITextField文本输入框 */ UITextField * textField = [[UITextField alloc]initWithFrame:CGRectMake(50, 50 ...
- 一个基于DpperHelper的t4模板
自定义模板,空的类(目的是和t4生成的模板分开,以免被覆盖) ExtensionDAL <#@ template debug="false" hostspecific=&qu ...
- 关于malloc和free函数的用法
原文:http://blog.pfan.cn/vfdff/33507.html 个人总结 在C语言的学习中,对内存管理这部分的知识掌 握尤其重要!之前对C中的malloc()和free()两个函数的了 ...
- 《JS权威指南学习总结--第二章词法结构》
第二章词法结构 内容要点: 一.注释 1. //表示单行注释 2. /*这里是一段注释*/ 3.一般编辑器里加注释是:选中要加注释的语句,按 ctrl+/ 二.直接量 所谓直接量,就是程序中直接使用的 ...
- allocator 类
allcator是一个模板类 定义在memory头文件中,将内存分配与对象构造分开,分配的内存是原始的.未构造的 一.how to use 因其实一个类,则使用allcator时需要首先声明一个类对象 ...
- qsdk编译
QSDK是一种在openwrt的基础上,加入了高通atheros芯片相关资料的一种环境. QSDK与openwrt的区别主要在如下几个方面: arch/mips/ath79/* – updated Q ...
- OPENWRT make menuconfig错误之一
1.make menuconfig rm: cannot remove `tmp/.host.mk': Permission denied 退到trunk上级目录sudo chown -R 777 t ...
- svn revert
本地开发环境出现一个问题,用revert完美解决. 问题描述: 文件static/image/common/jiqiaodaren.png已经被提交到svn上,但是我的开发环境因未与svn同步,所以没 ...