1.3.5.1. 多对一关系
要定义一个多对一关系,请使用ForeignKey。ForeignKey的用法和其它字段类型一样:把它包含在你的模型的类属性中。
ForeignKey需要一个位置参数:该模型相关的类。
例如,如果Car模型有一个Manufacturer,一个Manufacturer制造多辆汽车,但每个Car只有一个Manufacturer,那么应该定义如下:
(笔记:文章和分类的关系就是多对一关系)
class Manufacturer(models.Model):
#...
class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer)
#...
你也可以创建循环关系(一个带有到自己的多对一关系的对象)和到未定义的模型的关系;详情请参阅“模型字段参考(URL)”。
建议但不强制要求ForeignKey字段的名字是模型的小写字母的名字(例如在上例中使用的manufacturer)。当然你可以使用任何你想要的名字,例如:
class Car(models.Model):
company_that_makes_it = models.ForeignKey(Manufacturer)
#...
参阅“多对一关系模型的例子(URL)”来看一下完整的例子。
ForeignKey字段也接受一些额外的参数,可以参阅“模型字段参考(URL)”。这些选项帮助你定义关系的工作方式,不过它们都是可选的。
1.3.5.2. 多对多关系
要定义多对多关系,请使用ManyToManyField。它的使用方法和其它字段类型一样:把它包含在你的模型的类属性中。
ManyToManyField要求一个位置参数:该模型相关的类。
例如,一个Pizza有多个Topping对象——也就是一个Topping可以在多个比萨上,每个Pizza有多个Toppings——这种情况我们可以这样定义:
(笔记:文章和标签的关系就是多对多关系)
class Topping(models.Model):
#...
class Pizza(models.Model):
#...
toppings = models.ManyToManyField(Topping)
和Foreign一样,你也可以创建循环关系(带有到自己的多对多关系的对象)和到未定义模型的关系;详情参阅“模型字段参考(URL)”。
建议但不强制要求ManyToManyField的名字(上面的例子中的toppings)是复数形式,复数形式是为了描述相关模型对象的集合。
哪个模型带有ManyToManyField都没关系,但你只能在其中一个模型中使用它,而不能在两个模型中都使用它。
一般来说,ManyToManyField实例应该放在Django管理界面中被编辑的对象中。在上面的例子中,toppings在Pizza中(而不是Topping有pizzas ManyToManyField),因为一个比萨有多个掐尖儿比一个掐尖儿在多个比萨上更容易考虑。这就是上面我们使用的方式,Pizza管理表单将让用户选择掐尖儿。
参阅“多对多关系模型的例子(URL)”来看一下完整的例子。
ManyToManyField字段也接受一些额外的参数,这些参数在“模型字段参考(URL)”中解释。这些选项帮助你定义关系的工作方式,不过它们都是可选的。
1.3.5.3. 多对多关系的额外字段(Django 1.0新增)
当你只需要处理简单的多对多关系,就像混合和匹配比萨和掐尖儿,一个标准的ManyToManyField字段就是你全部的所需。然而,有些时候你需要让数据在两个模型之间产生联系。
例如,考虑一下跟踪乐队和乐队拥有的音乐家的应用程序的例子。这是一个人和这个人所在团队之间的多对多关系,因此你可以使用ManyToManyField来描述这个关系。然而,这种成员关系有很多你想要搜集的细节,比如这个人加入团队的时间。
对于这种情况,Django让你可以指定用来管理多对多关系的模型。然后你可以在中间模型中放入额外的字段。中间模型使用through参数指向像中间人一样工作的模型,来和ManyToManyField发生关系。对于四个音乐家的例子,代码可能像这样子:
class Person(models.Model):
name = models.CharField(max_length=128)
def __unicode__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __unicode__(self):
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
当你建立中间模型时,你需要为模型明确地指定外键,以建立多对多关系。这个明确的声明定义了两个模型是如何产生联系的。
对于中间模型,有一些限制:
中间模型必须包含并且只包含一个到目标模型的外键(在上面的例子中是Person)。如果存在一个以上的到目标模型的外键,会产生校验错误。
中间模型必须包含并且只包含一个到源模型的外键(在上面的例子中是Group)。如果存在一个以上的到源模型的外键,会产生校验错误。
唯一的例外是,对于通过一个中间模型,带有到自己的多对多关系的模型。在这种情况下,两个到同一个模型的外键是允许的,但这两个外键会被看作是多对多关系的两个不同侧面。
当使用中间模型来定义一个到自己的多对多关系的模型是,你必须使用symmetrical=False(参阅“模型字段参考(URL)”)。
现在你已经建立了ManyToManyField来使用中间模型(在这个例子中是MemberShip),你可以开始创建一些多对多的对应关系了。具体来说是创建中间模型的一些实例:
>>> ringo = Person.objects.create(name='Ringo Starr')
>>> paul = Person.objects.create(name='Paul McCartney')
>>> beatls = Group.objects.create(name='The Beatles')
>>> m1 = Membership(person=ringo, group=beatles,
... date_joined=date(1962, 8, 16),
... invite_reason='Needed a new drummer.')
>>> m1.save()
>>> beatles.members.all()
[<Person: Ringo Starr>]
>>> ringo.group_set.all()
[<Group: The Beatles>]
>>> m2 = Membership.objects.create(person=paul, group=beatles,
... date_joined=date(1960, 8, 1),
... invite_reason='Wanted to form a band.')
>>> beatles.members.all()
[<Person:Ringo Starr>, <Person: Paul McCartney>]
和一般的多对对字段不同,你无法使用add、create或赋值(例如,beatles.members = [...])来创建关系:
#THIS WILL NOT WORK
>>> beatles.members.add(john)
#NEITHER WILL THIS
>>> beatles.members.create(name='George Harrison')
#ADD NEITHER WILL THIS
>>> beatles.members = [john, paul, ringo, george]
为什么呢?你不能只在Person和Group创建关系,你必须指定Membership模型需要的全部关系细节。简单的add、create和赋值调用没有提供方法来指定这些额外的信息。结果就是,对于使用中间模型的多对多关系它们被禁用了。创建这种类型的关系的唯一方法是创建中间模型的实例。
#Beatles have broken up
>>> beatles.members.clear()
一旦你通过创建中间模型的实例建立了多对多关系,你就可以进行查询了。就像普通的多对多关系那样,你可以使用多对多关系模型的属性来进行查询:
#Find all the groups with a member whose name starts with 'Paul'
>>> Group.objects.filter(memebers__name__startwith='Paul')
[<Group: The Beatles>]
因为你正在使用中间模型,你也可以使用它的属性来进行查询:
#Find all the members of the Beatles that joined after Jan 1 1961
>>> Person.objects.filter(
... group__name='The Beatles',
... membership__date__joined__gt=date(1961, 1, 1))
[<Person: Ringo Starr]
1.3.5.4. 一对一关系
要定义一对一关系,请使用OneToOneField。它的使用方法和其它字段一样:把它包含在模型的类属性中。
当对象以某种方式扩展了另一个对象的主键时,这对于对象的主键是最重要的。
OneToOneField要求一个位置参数:该模型相关的类。
例如,如果你将创建一个数据表places,你可能会在数据表中建立一些相当标准的东西,就像地址、电话号码等等。然后,如果你想在places上建立一个饭馆,你可以不必重复劳动,在Restaurant模型中复制这些字段,你可以建立一个带有到Place的OneToOneField(因为饭馆就是一个place;实际上,对于这种情况典型的做法是使用继承,这实际上是一种隐式的一对一关系)。
和外键一样,你可以定义循环关系和到未定义模型的关系;详情请参阅“模型字段参考(URL)”。
请参阅“一对一关系模型的例子(URL)”来看一下完整的例子。
OneToOneField也接受一个可选的参数,这个参数在“模型字段参考(URL)”有介绍。
OneToOneField类曾经会自动成为模型的主键。现在情况不再如此了(尽管如果你愿意你可以手动传递一个primary_key参数)。因此,现在一个模型可以拥有多个OneToOneField类型的字段。
1.3.6. 跨文件模型
在当前模型中建立和另一个应用程序中的模型的关系是非常完美没有问题的。要建立这样的关系,在当前模型所在文件的头部导入相关模型,然后在需要的时候引用相关模型即可。例如:
from mysite.geography.models import ZipCode
class Restaurant(models.Model):
#...
zip_code = models.ForeignKey(ZipCode)
1.3.7. 字段名限制
Django对字段名只有两个限制:
1) 字段名不能是Python的保留关键字,不然会导致Python语法错误。例如:
class Example(models.Model):
pass = models.IntegerField() #"pass" is a reserved word!
2) 字段名在一行中包含一个以上的下划线,这和Django的搜索查询语法的工作方式有关。例如:
class Example(models.Model):
foo_bar = models.IntegerField() #"foo__bar"有两个下划线!
这些限制是可以绕过的,因为你的字段名并不需要和数据表的列名匹配。请参考db_colum选项。
SQL保留字,比如join、where或select,可以用作模型字段名,因为Django在进行底层的SQL查询前会对所有数据表名和列名进行转义。具体来说是使用你所使用的数据库的引用语法。
本文引自:http://bbs.quickbest.com.cn/thread-63321-1-1.html
这里有更全的资料。
分享到:
相关推荐
对于数据库, django 有自己的一套 ORM(对象关系映射), 或许其他的框架可以随意更换 ORM, 但 django 不建议这么做. 因为 django 内置有很多的 model, 这些 model 无疑是用 django 内置 ORM 实现的, 如果更换后, 内置...
用于创建模型的对象关系映射 2. 为最终用户设计的完美管理界面 3. 一流的 URL 设计 4. 设计者友好的模板语言 5. 缓存系统。 在Django中,控制器接受用户输入的部分由框架自行处理,所以 Django 里更关注的是模型...
Django-pb-model提供模型混合映射/转换protobuf消息。 支持从protobuf消息定义自动生成模型。 当前支持基本值字段和幼稚的关系转换,包括: 整数,字符串,浮点数,布尔值 选择字段 约会时间 外键和多对多关系 ,...
- 用于创建模型的对象关系映射; - 为最终用户设计较好的管理界面; - URL 设计; - 设计者友好的模板语言; - 缓存系统。 Django已经成为web开发者的首选框架,是一个遵循 MVC 设计模式的框架。MVC是Model、View、...
对象关系映射(Object Relation Mapping) 实现了对象和数据库之间的映射 隐藏了数据访问的细节,不需要编写SQL 编写Models: 1、在应用根目录下创建models.py,并引入models模块 2、创建类,继承models.Model,该类...
补充知识:Django框架MySQL数据库到models模型的映射关系 一、前言 我的数据库已经用MySQL Workbench设计好了,也插入了一些测试数据,现在开始在Django中设计models模型。本以为顺风顺水,没想到也遇到一些bug,...
将带注释的字典列表映射到 Django 模型中 用法 用 django-d2m 函数包装你的 django 查询集或列表 from django_d2m import queryset_to_model queryset = CashUsageLog . objects . values ( 'product__episode__...
django-simple-yandex-map 将Yandex映射轻松集成到django管理面板中安装===将django_ymap文件夹复制到django项目的根目录。 将django_ymap添加到INSTALLED_APPS ( settings.py文件) INSTALLED_APPS = ( ... '...
django中设计数据模型类是基于ORM的对象关系映射更方便的进行数据库中的数据操作。 对象关系映射 把面向对象中的类和数据库表–对应,通过操作类和对象,对数表实现数据操作,不需要写sql,由ORM框架生成 django...
Django简介: Django是一个开放源代码的Web应用框架,由Python写成。采用了MVC的框架模式,即...django是对象关系映射的 (ORM,object-relational mapping):以Python类形式定义你的数据模型,ORM将模型与关系数据库连接
了解Django的表明和models名称的映射关系就可以让Django使用已经存在的表。 假如在Django存在models如下: from django.db import models # Create your models here. class Sciencenews(models.Model
最好使用这三个名称作为model的属性名,你可以通过db_column属性映射数据库中对应的字段,如果实在无法做到则需要在form中定义表单项的id为id_address、id_location和id_city。 使用与属性对应的字段类AddressField...
模型(Model):提供数据访问接口和模块,包括数据字段、元数据、数据关系等定义及操作。 视图(View):django视图封装了HTTP Request和Response的一系列操作和数据流,主要功能包括URL映射机制、绑定模板等 模板...
对于 ORM 定义: 对象关系映射, Object Relational Mapping, ORM, 是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象...
但是在Django中,控制器接受用户输入的部分由框架自行处理,所以 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),称为 MTV模式。它们各自的职责如下: 层次 职责 模型(Model),即数据...
Django 本身自带了一个很强大的ORM,支持自定义model并将其映射到数据库的表中 model中可以定义各种类型的数据,比较直观的比如整形, 字符型,也可以定义外键 ForeignKey来指定一对多关系。 关系数据库中有一种多对...
基类里面的save_model和delete_model函数可以做数据对象的新建和删除的预处理和后处理。自建的函数如果要redirect到自己建的view,反向映射要包含admin:,写成 return HttpResponseRedirect(reverse('admin:manage
灵活的URL映射:Django使用正则表达式管理URL映射,灵活性高。 丰富的Template模板语言:类似jinjia模板语言,不但原生功能丰富,还可以自定义模板标签。 自带免费的后台管理系统:只需要通过简单的几行配置和代码就...
中文意为 对象-关系映射. 在MVC/MVT设计模式中的Model模块中都包括ORM 2.ORM优势 (1)只需要面向对象编程, 不需要面向数据库编写代码. 对数据库的操作都转化成对类属性和方法的操作. 不用编写各种数据库的sql...
MVC和MTV框架 MVC Web服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,... M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。 T 代表模板 (Template):负