settings 文件内:
DATABASES = { ' default ' : { ' ENGINE ' : ' django.db.backends.postgresql_psycopg2 ' , ' NAME ' : ' mydatabase ' , ' USER ' : ' mydatabaseuser ' , ' PASSWORD ' : ' mypassword ' , ' HOST ' : ' 127.0.0.1 ' , ' PORT ' : ' 5432 ' , } }
如果是 SQLite,则只需填写 engine 和 name,SQLite 的 name 应当包含可靠路径(因为没有 server):
DATABASES = { ' default ' : { ' ENGINE ' : ' django.db.backends.sqlite3 ' , ' NAME ' : ' mydatabase ' , } }
测试数据库配置:
>>> from django.db import connection >>> cursor = connection.cursor()
django 的 ORM 示例,定义在 app 下的 models 文件内,具体支持的字段参考官方文档:
from django.db import models class Book(models.Model): title = models.CharField(max_length = 100 ) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField()
django 使用额外一张单独的表来管理多对多联系。
在部署模型前,首先应保证相应的 app 是已安装状态,这在 settings 文件内的 INSTALLED_APPS 字段内进行设置。
python manage.py validate
python manage.py sqlall books
这里的 books 是 app 的名称。运行后输出如下:
BEGIN ; CREATE TABLE "books_publisher" ( "id" serial NOT NULL PRIMARY KEY , "name" varchar ( 30 ) NOT NULL , "address" varchar ( 50 ) NOT NULL , "city" varchar ( 60 ) NOT NULL , "state_province" varchar ( 30 ) NOT NULL , "country" varchar ( 50 ) NOT NULL , "website" varchar ( 200 ) NOT NULL ) ; CREATE TABLE "books_author" ( "id" serial NOT NULL PRIMARY KEY , "first_name" varchar ( 30 ) NOT NULL , "last_name" varchar ( 40 ) NOT NULL , "email" varchar ( 75 ) NOT NULL ) ; CREATE TABLE "books_book" ( "id" serial NOT NULL PRIMARY KEY , "title" varchar ( 100 ) NOT NULL , "publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id") DEFERRABLE INITIALLY DEFERRED, "publication_date" date NOT NULL ) ; CREATE TABLE "books_book_authors" ( "id" serial NOT NULL PRIMARY KEY , "book_id" integer NOT NULL REFERENCES "books_book" ("id") DEFERRABLE INITIALLY DEFERRED, "author_id" integer NOT NULL REFERENCES "books_author" ("id") DEFERRABLE INITIALLY DEFERRED, UNIQUE ("book_id", "author_id") ) ; CREATE INDEX "books_book_publisher_id" ON "books_book" ("publisher_id"); COMMIT ;
注意:
python manage.py syncdb
在 python manage.py shell 命令行内执行 INSERT 操作的方法是实例化一个模型对象,并调用其 .save() 方法
>>> from books.models import Publisher >>> p1 = Publisher(name = ' Apress ' , address = ' 2855 Telegraph Avenue ' , ... city = ' Berkeley ' , state_province = ' CA ' , country = ' U.S.A. ' , ... website = ' http://www.apress.com/ ' ) >>> p1.save()
不过这个 save() 方法在用于 UPDATE 功能时,实际执行的是更新整行而不仅是修改过的属性。这可能会引起竞态条件,如果想只更新一个属性,应当调用结果集的 .update() 方法:
>>> Publisher.objects.filter(id = 52 ).update(name = ' Apress Publishing ' )
update() 方法返回一个整数,表示受影响的行数。
.delete() 方法与 .update() 类似,都是作用于结果集的方法。但出于安全考虑,在删除表中所有元组时,需要显示调用 .all() 方法:
>>> Publisher.objects.delete() Traceback (most recent call last): File " <console> " , line 1 , in < module > AttributeError: ' Manager ' object has no attribute ' delete ' >>> Publisher.objects.all().delete()
如果想 print 出 Publisher 对象的内容,需要在定义模型时写好 __str__() 方法。
>>> publisher_list = Publisher.objects.all() >>> publisher_list [ < Publisher: Publisher object > , < Publisher: Publisher object > ]
>>> Publisher.objects.filter(name = ' Apress ' [, *** ]) [ < Publisher: Apress > ]
注意这里是双下划线 __contains
>>> Publisher.objects.filter(name__contains = " press " ) [ < Publisher: Apress > ]
filter() 返回的总是一个容器对象,这个对象实现了列表的操作方法(一如既往不包括负索引),因此总是可以使用比如 for 循环来迭代其中的元素。对应的有一个 get() 方法,这个方法要求满足条件的元素有且只有一个,否则引发异常。
>>> Publisher.objects.order_by( " state_province " , " address " )
第二个参数仅在第一个参数相同时起作用,排序还可以在属性前加“-”来实现逆序:
>>> Publisher.objects.order_by( " -name " )
.ordered_by() 可作用于结果查询结果对象集,所以 filter() 返回的结果也可以支持。
或者,直接在模型定义的地方指定默认排序方式:
class Publisher(models.Model): name = models.CharField(max_length = 30 ) . . . class Meta: ordering = [ ' name ' ]
当访问外键字段时,会得到相应的模型对象:
>>> b = Book.objects.get(id = 50 ) >>> b.publisher < Publisher: Apress Publishing > >>> b.publisher.website u ' http://www.apress.com/ '
而当通过外键反向追溯时,则会获得一个模型对象的 QuerySet,这个对象与前面一样也支持过滤和分切操作。实现这类访问使用的属性名是由模型名称的小写 + _set 组成的:
>>> p = Publisher.objects.get(name = ' Apress Publishing ' ) >>> p.book_set.all() [ < Book: The Django Book > , < Book: Dive Into Python > , ...] >>> p.book_set.filter(name__icontains = ' django ' ) [ < Book: The Django Book > , < Book: Pro Django > ]
多对多和外键工作方式相同,只不过处理的是QuerySet而不是模型实例:
>>> b = Book.objects.get(id = 50 ) >>> b.authors.all() [ < Author: Adrian Holovaty > , < Author: Jacob Kaplan - Moss > ] >>> b.authors.filter(first_name = ' Adrian ' ) [ < Author: Adrian Holovaty > ] >>> b.authors.filter(first_name = ' Adam ' ) []
反向查询也可以。 要查看一个作者的所有书籍,使用author.book_set ,就如这样:
>>> a = Author.objects.get(first_name = ' Adrian ' , last_name = ' Holovaty ' ) >>> a.book_set.all() [ < Book: The Django Book > , < Book: Adrian ' s Other Book>]
先前提到过,syncdb 命令只添加新表,并不会把已有模型的更新同步到数据库中。实际上,django 对已有 模型 与 数据库 之间的对应关系仅作最低限度的检查——即:模型中的字段在数据库中必须有,否则会引发运行时错误(在用户进行查询的时候);至于数据库中是否存在模型里并未定义的字段,django 并不关心,因为数据库中多余的字段并不影响 django 依据模型做正常的查询。(django 在做 orm 到 sql 语句的转化时,总是会明确指出要查询的字段)
基于这种逻辑,想要修改数据库模式应该采用的方法就是:在不引发运行时错误的前提下,按特定顺序分别修改数据库和模型。具体顺序为:
在形如 Book.objects.all() 的语句中,objects 作为 models.Model 类的一个特殊属性,他是 models.Manager 的实例。有些时候我们可以通过自定义这个属性来实现一些特别的方法,或修改 manager 返回的 QuerySets 。
这需要子类化一个 Manager 对象,再把它绑定到具体的模型中,比如:
# models.py from django.db import models # ... Author and Publisher models here ... class BookManager(models.Manager): def title_count(self, keyword): return self.filter(title__icontains = keyword).count() 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) objects = BookManager() def __unicode__ (self): return self.title
有了这个manager,我们现在可以这样做:
>>> Book.objects.title_count( ' django ' ) 4 >>> Book.objects.title_count( ' python ' ) 18
manager的基本QuerySet返回系统中的所有对象。 例如,`` Book.objects.all()`` 返回数据库book中的所有书本。我们可以通过覆盖Manager.get_query_set()方法来重写manager的基本QuerySet。 get_query_set()按照你的要求返回一个QuerySet。
from django.db import models # First, define the Manager subclass. class DahlBookManager(models.Manager): def get_query_set(self): return super(DahlBookManager, self).get_query_set().filter(author = ' Roald Dahl ' ) # Then hook it into the Book model explicitly. class Book(models.Model): title = models.CharField(max_length = 100 ) author = models.CharField(max_length = 50 ) # ... objects = models.Manager() # The default manager. dahl_objects = DahlBookManager() # The Dahl-specific manager.
在这个示例模型中,Book.objects.all()返回了数据库中的所有书本,而Book.dahl_objects.all()只返回了Roald Dahl的书。
这个例子也说明了另外一件事情,就是一个模型可以有多个 manager 属性。你只需要给他们做好命名就可以了(不要再用 objects)。
注意:django 会把模型中定义的第一个 manager 作为默认 manager 使用,如果你重写了任何一个 manager 的话。所以当你给模型添加 manager 的时候,一定记得在最前面把 models.Manager 绑定给 objects 。
模型方法就是模型里定义的方法,跟普通类里定义的方法没什么不同。
使用 DB-API 即可。