文档章节

修改django-模型方法

 我的去哈哈
发布于 2015/04/26 11:24
字数 1846
阅读 234
收藏 0
点赞 0
评论 0

Migrations

Django中对Model进行修改是件麻烦的事情,syncdb命令仅仅创建数据库里还没有的表,它并不对已存在的数据表进行同步修改,也不处理数据模型的删除。 如果你新增或修改数据模型里的字段,或是删除了一个数据模型,你需要手动在数据库里进行相应的修改或者使用South。Django 1.7中已经集成了South的代码,提供了3个新命令:

  • migrate: 用于执行迁移动作,具有syncdb的功能

  • makemigrations: 基于当前的model创建新的迁移策略文件

  • sqlmigrate: 显示迁移的SQL语句,具有sqlall的功能

使用起来很简单,对Model做了修改后,使用makemigrations记录修改:

$ python manage.py makemigrations
Migrations for 'books':
  0003_auto.py:
    - Alter field author on book

你的Model会被扫描, 然后与migrations文件夹中以前的版本作比较, 然后生成本次迁移文件。

有了新的migration文件,就可以使用migrate修改数据库模式:

$ python manage.py migrate
Operations to perform:
  Synchronize unmigrated apps: sessions, admin, messages, auth, staticfiles, contenttypes
  Apply all migrations: books
Synchronizing apps without migrations:
  Creating tables...
  Installing custom SQL...
  Installing indexes...
Installed 0 object(s) from 0 fixture(s)
Running migrations:
  Applying books.0003_auto... OK

也可以针对单独的app生成migration:

$ python manage.py makemigrations your_app_label

也可以对数据库中的数据进行修改,首先建立一个空的migration文件:

python manage.py makemigrations --empty yourappname

文件的内容如下:

# -*- coding: utf-8 -*-from django.db import models, migrationsclass Migration(migrations.Migration):

    dependencies = [
        ('yourappname', '0001_initial'),
    ]

    operations = [
    ]

如果想修改某个Model例如Person的数据,设置其name字段:

# -*- coding: utf-8 -*-from django.db import models, migrationsdef combine_names(apps, schema_editor):  # We can't import the Person model directly as it may be a newer  # version than this migration expects. We use the historical version.  Person = apps.get_model("yourappname", "Person")  for person in Person.objects.all():    person.name = "%s %s" % (person.first_name, person.last_name)    person.save()class Migration(migrations.Migration):  dependencies = [    ('yourappname', '0001_initial'),  ]  operations = [    migrations.RunPython(combine_names),  ]

最后运行 python manage.py migrate 即可。这样Person中的所有对象的name字段都设置好了。

依据Model修改关系数据库是开发中的一个重要的问题,解决这个问题可以提升开发速度,不过要在生产环境中随便使用migrate操作数据库还是很危险的,有时候需要手动修改数据库。

手动修改数据库

当处理模型修改的时候:

  • 如果模型包含一个未曾在数据库里建立的字段,Django会报出错信息。 当你第一次用Django的数据库API请求表中不存在的字段时会导致错误。

  • Django不关心数据库表中是否存在未在模型中定义的列。

  • Django不关心数据库中是否存在未被模型表示的table。

添加字段

  1. 在你的模型里添加字段。下例向Book模型添加num_pages字段:

    class Book(models.Model):  title = models.CharField(max_length=100)  authors = models.ManyToManyField(Author)  publisher = models.ForeignKey(Publisher)  publication_date = models.DateField()  **num_pages = models.IntegerField(blank=True, null=True)**  def __unicode__(self):    return self.title 
  1. 运行manage.py sqlall yourappname来测试模型新的CREATE TABLE语句。

    CREATE TABLE "books_book" (  "id" serial NOT NULL PRIMARY KEY,  "title" varchar(100) NOT NULL,  "publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id"),  "publication_date" date NOT NULL,  "num_pages" integer NULL);
  1. 开启你的数据库的交互命令界面(比如,psql或者mysql,或者可以使用manage.py dbshell。 执行ALTER TABLE语句来添加新列。

    ALTER TABLE books_book ADD COLUMN num_pages integer;  

添加 非NULL 字段

先创建 NULL 型的字段,然后将该字段的值填充为某个默认值,然后再将该字段改为 NOT NULL 型

BEGIN;ALTER TABLE books_book ADD COLUMN num_pages integer;UPDATE books_book SET num_pages=0;ALTER TABLE books_book ALTER COLUMN num_pages SET NOT NULL;COMMIT;

添加ForeignKey或ManyToManyField

添加外键即是添加key_id的integer字段,添加多对多字段是创建一个新的数据表。

删除字段

比较简单,将表中的某列删掉即可

ALTER TABLE books_book DROP COLUMN num_pages;

使用sqlite3时,会有些麻烦,sqlite3不支持删除列操作,只有有限地 ALTER TABLE 支持。你可以使用它来在表的末尾增加一列,可更改表的名称。 如果需要对表结构做更复杂的改变,则必须重新建表。重建时可以先将已存在的数据放到一个临时表中,删除原表, 创建新表,然后将数据从临时表中复制回来。

如,假设有一个 t1 表,其中有 "a", "b", "c" 三列, 如果要删除列 c :

BEGIN TRANSACTION;CREATE TEMPORARY TABLE t1_backup(a,b);INSERT INTO t1_backup SELECT a,b FROM t1;DROP TABLE t1;CREATE TABLE t1(a,b);INSERT INTO t1 SELECT a,b FROM t1_backup;DROP TABLE t1_backup;COMMIT;

删除多对多关联字段

删掉多对多关联的数据表即可

DROP TABLE books_book_authors;

删除模型

删除数据表即可

DROP TABLE books_book;

数据迁移

django 项目提供了一个导出的方法 python manage.py dumpdata, 不指定 appname 时默认为导出所有的app

python manage.py dumpdata myapp > myapp.json

导出的文件内容格式:

[
  {
    "model": "myapp.person",
    "pk": 1,
    "fields": {
      "first_name": "John",
      "last_name": "Lennon"
    }
  },
  {
    "model": "myapp.person",
    "pk": 2,
    "fields": {
      "first_name": "Paul",
      "last_name": "McCartney"
    }
  }]

数据导入:

python manage.py loaddata myapp.json

导出用户数据:

python manage.py dumpdata auth > auth.json

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

我们已经实现了卖方的产品维护界面,根据最初的需求,还要为买方实现一个目录页:买方通过这个界面浏览产品并可以加入购物车。通过进一步需求调研,了解到产品有一个“上架时间”,在这个时间之后的产品才能被买方看到。并且买方应该先看到最新的产品。

我们注意到,这个“新需求”需要对Product进行调整,增加一个日期属性date_available来保存“上架时间”。如同开发新功能一样,在修改的时候也应该从model开始。

为Model类增加一个属性很容易:

 

  1. class Product(models.Model):

  2. title = models.CharField(max_length=100,unique=True)

  3. description     = models.TextField()

  4. image_url = models.URLField(max_length=200)

  5. price = models.DecimalField(max_digits=8,decimal_places=2)

  6. date_available = models.DateField()


问题在于,model类的改变需要对数据库表也进行同样的修改。你可能想到前面介绍过的python manage.py syncdb, 但是很遗憾这个命令现在不起作用了。因为syncdb仅仅创建数据库里还没有的表,它 并不 对你数据模型的修改进行同步,也不处理数据模型的删除。 如果你新增或修改数据模型里的字段,或是删除了一个数据模型,你需要手动在数据库里进行相应的修改。 当然,在开发环境你可以drop相应的表,然后运行syncdb重新创建。但是这样做对于发布环境没有任何帮助,所以我们最好这样做:
1. 使用sqlall查看模型新的 CREATE TABLE 语句。 查看新创建的字段:
$ python manage.py sqlall depotapp
BEGIN;
CREATE TABLE "depotapp_product" (
"id" integer NOT NULL PRIMARY KEY,
"title" varchar(100) NOT NULL UNIQUE,
"description" text NOT NULL,
"image_url" varchar(200) NOT NULL,
"price" decimal NOT NULL,
"date_available" date NOT NULL
)
;
COMMIT;


2. 使用数据库命令行工具,或客户端工具,或者django提供的dbshell工具增加字段:
$ python manage.py dbshell
sqlite> begin;
sqlite> alter table depotapp_product add column date_available date not null default 0;
sqlite> commit;

3. 验证数据库:
$ python manage.py shell
>>> from depot.depotapp.models import Product
>>> Product.objects.all()
如果没有异常发生,则可以在发布环境进行上述修改。

 

以上是在模型中增加一个属性的步骤。其他对模型的修改可能还有:

删除字段——drop column

删除模型——drop table

删除多对多关联——drop table (自动生成的关联表)

也需要参考上述的步骤进行。


© 著作权归作者所有

共有 人打赏支持
粉丝 3
博文 51
码字总数 55253
作品 0
东城
Django Book 2.0 笔记——Model

配置数据库: settings 文件内: DATABASES = { } 如果是 SQLite,则只需填写 engine 和 name,SQLite 的 name 应当包含可靠路径(因为没有 server): DATABASES = { } 测试数据库配置: >>...

lionets ⋅ 2014/03/31 ⋅ 0

第十章: 数据模型高级进阶

第十章: 数据模型高级进阶 在第5章里,我们介绍了Django的数据层如何定义数据模型以及如何使用数据库API来创建、检索、更新以及删除记录 在这章里,我们将向你介绍Django在这方面的一些更高...

阿帆提 ⋅ 2016/11/10 ⋅ 0

基于 Django1.5自定义user模型

今天看到 http://my.oschina.net/lxcong/blog/145260这篇 blog有感,所以将自己的使用经验整理出来给大家做一个参考。 Django自带的user模型在权限粒度切分,session控制,用户认证方面整合的很...

AlanShi ⋅ 2013/07/20 ⋅ 24

第五章 模型

第五章 模型 在第三章,我们讲述了用 Django 建造网站的基本途径: 建立视图和 URLConf 。 正如我们所阐述的,视图负责处理一些主观逻辑,然后返回响应结果。 作为例子之一,我们的主观逻辑是...

阿帆提 ⋅ 2016/11/10 ⋅ 0

django2.0入门教程第二节

继上篇 django2.0入门教程第一节,生成了投票应用,接下来讲解如何使用django的模型与数据库进行交互 数据库设置 打开mysite/settings.py,可看到默认情况下,django使用的是sqlite3数据库 ...

钟森龙 ⋅ 2017/12/31 ⋅ 0

diango创建的一个简单的基本流程

高内聚,低耦合 高内聚:一个模块内部一个功能。 低耦合:每个模块各司其职,尽量零关联。 创建django项目 1、django-admin startproject hero(项目名称) 进入hero目录,目录结构如下图: ...

AAA年华 ⋅ 2017/12/25 ⋅ 0

Django中扩展User模型

官方其实是有资料的,不过在这里还是写的浅显点。 官方地址https://docs.djangoproject.com/en/dev/topics/auth/customizing/ 在实际开发过程中,django提供的user字段肯定是不够用的,比如用...

spider1983 ⋅ 2014/08/26 ⋅ 0

Django入门:第一个Django应用

对Django这个框架感兴趣好久了,却一直懒于研究学习,现在跟随官网的教程跑一遍,学学Django同时也继续学学Python。 在开始之前,我们先把Python和Django这个框架安装好。 官网:https://www...

durban ⋅ 2012/04/30 ⋅ 0

django 1.8 官方文档翻译: 2-1-3 元选项 (初稿)

Django 文档协作翻译小组人手紧缺,有兴趣的朋友可以加入我们,完全公益性质。 交流群:467338606 网站:http://python.usyiyi.cn/django/index.html 模型元选项 这篇文档阐述了所有可用的元...

apachecn_飞龙 ⋅ 2015/07/23 ⋅ 0

Django模型类Meta元数据详解

简介 使用内部的class Meta 定义模型的元数据,例如: 当orderwithrespectto 设置之后,模型会提供两个用于设置和获取关联对象顺序的方法:getRELATEDorder() 和setRELATED_order(),其中REL...

楠木楠 ⋅ 2016/09/25 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Java NIO之字符集

1 字符集和编解码的概念 首先,解释一下什么是字符集。顾名思义,就是字符的集合。它的初衷是把现实世界的符号映射为计算机可以理解的字节。比如我创造一个字符集,叫做sex字符集,就包含两个...

士别三日 ⋅ 37分钟前 ⋅ 0

Spring Bean基础

1、Bean之间引用 <!--如果Bean配置在同一个XML文件中,使用local引用--><ref bean="someBean"/><!--如果Bean配置在不同的XML文件中,使用ref引用--><ref local="someBean"/> 其实两种......

霍淇滨 ⋅ 42分钟前 ⋅ 0

05、基于Consul+Upsync+Nginx实现动态负载均衡

1、Consul环境搭建 下载consul_0.7.5_linux_amd64.zip到/usr/local/src目录 cd /usr/local/srcwget https://releases.hashicorp.com/consul/0.7.5/consul_0.7.5_linux_amd64.zip 解压consu......

北岩 ⋅ 45分钟前 ⋅ 0

Webpack 4 api 了解与使用

webpack 最近升级到了 v4.5+版 01 官方不再支持 node4 以下版本 官方不再支持 node4 以下版本官方不再支持 node4 以下的版本,所以如果你的node版本太低,先开始升级node吧!话说node10 ...

NDweb ⋅ 55分钟前 ⋅ 0

使用nodeJs安装Vue-cli

Vue脚手架就是一个Vue框架开发环境 脚手架的意思是帮你快速开始一个vue的项目,也就是给你一套vue的结构,包含基础的依赖库,只需要 npm install就可以安装,让我们不需要为了编辑或者一些其...

木筏笔歆 ⋅ 今天 ⋅ 0

【微信小程序开发实战】0x00.开发前准备工作

写在开始 本人资深后端码农一枚,近期项目需求,接触到了微信小程序,将学习过程整理成文分享给小伙伴们,由于是边学边整理难免有表述不对的地方,望大家及时指正,感谢。 本人微信号: dream...

dreamans ⋅ 今天 ⋅ 0

linux redis的安装和php7下安装redis扩展

安装redis服务器 (1)下载安装包: $ wget http://download.redis.io/releases/redis-2.8.17.tar.gz (2)编译程序: $ tar xzf redis-2.8.17.tar.gz $ cd redis-2.8.17 $ make $ cd src &&......

concat ⋅ 今天 ⋅ 0

Guava EventBus源码解析

一、EventBus使用场景示例 Guava EventBus是事件发布/订阅框架,采用观察者模式,通过解耦发布者和订阅者简化事件(消息)的传递。这有点像简化版的MQ,除去了Broker,由EventBus托管了订阅&...

SaintTinyBoy ⋅ 今天 ⋅ 0

http怎么做自动跳转https

Apache 版本 如果需要整站跳转,则在网站的配置文件的<Directory>标签内,键入以下内容: RewriteEngine on RewriteCond %{SERVER_PORT} !^443$ RewriteRule ^(.*)?$ https://%{SERVER_NAME......

Helios51 ⋅ 今天 ⋅ 0

Python爬虫,抓取淘宝商品评论内容

作为一个资深吃货,网购各种零食是很频繁的,但是能否在浩瀚的商品库中找到合适的东西,就只能参考评论了!今天给大家分享用python做个抓取淘宝商品评论的小爬虫! 思路 我们就拿“德州扒鸡”...

python玩家 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部