`
zhizedai
  • 浏览: 16800 次
  • 性别: Icon_minigender_1
  • 来自: 大连
最近访客 更多访客>>
社区版块
存档分类
最新评论

Django model 关系映射

阅读更多
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)源码详解

    对于数据库, django 有自己的一套 ORM(对象关系映射), 或许其他的框架可以随意更换 ORM, 但 django 不建议这么做. 因为 django 内置有很多的 model, 这些 model 无疑是用 django 内置 ORM 实现的, 如果更换后, 内置...

    Django Model

    Django的ORM(对象关系映射)使得开发者可以使用Python类来定义数据库表结构,而无需直接编写SQL语句。这种高级抽象层极大地简化了数据库操作,并且支持多种数据库后端,如MySQL、PostgreSQL、SQLite等。 1. **定义...

    django外键关系的model互相读取数据.docx

    在Django中,模型(Model)是ORM(对象关系映射)的核心,它允许开发者用Python类来定义数据库表结构。在这个例子中,我们有三个模型:`Blog`、`Author`和`Entry`,它们之间存在外键(ForeignKey)和多对多...

    Django客户关系系统

    4. 数据库管理:Django内置了ORM(对象关系映射),允许开发者使用Python代码操作数据库,无需编写SQL。这使得数据模型的创建和管理变得简单,支持多种数据库系统如SQLite、MySQL、PostgreSQL等。 5. URL路由:...

    python django model联合主键的例子

    在Python的Django框架中,模型(Model)是ORM(对象关系映射)的核心部分,它允许开发者用Python类来定义数据库表结构。在某些情况下,我们可能需要为表设置联合主键,即多个字段共同构成唯一标识。本篇文章将详细...

    Django model class Meta原理解析

    元数据选项允许开发者对Django的ORM(对象关系映射)进行定制,以满足特定的需求。 1. **app_label**: - 当你的模型类不在默认的`models.py`文件中,即不在标准的应用程序包下时,你需要使用`app_label`来指定...

    PyPI 官网下载 | django-model-import-0.4.11.tar.gz

    同时,结合Django的ORM(对象关系映射)功能,可以方便地处理各种复杂的数据库操作。 总之,`django-model-import-0.4.11.tar.gz` 是一个针对Django的实用工具,它利用Python和PyPI的生态系统,为Python后端开发者...

    models_django管理_django_django的一个model_

    在Django框架中,Model是数据模型的抽象,它是Django ORM(对象关系映射)的核心部分,允许开发者用Python代码定义数据库表的结构。在这个特定的场景中,"models_django管理_django_django的一个model_"的标题暗示了...

    浅谈django model的get和filter方法的区别(必看篇)

    在Django框架中,ORM(对象关系映射)操作是非常重要的组成部分,能够极大地提高开发效率和代码可维护性。本文将深入探讨Django Model中的`get`和`filter`两种常用方法的区别,并通过实例进行详细解释。 #### 一、...

    Python库 | django-timestampable-model-0.1.3.tar.gz

    `django-timestampable-model`库的设计理念是开箱即用,它遵循Django的ORM(对象关系映射)规则,与Django的其他功能无缝集成。这意味着开发者可以像处理任何其他Django模型一样处理这些带有时间戳的模型,包括查询...

    Django框架 Django 2.1.7

    - **模型(Model)**:负责数据模型的定义和数据库交互,通过ORM(对象关系映射)使得开发者可以用Python代码操作数据库,无需关注SQL细节。 - **模板(Template)**:用于处理静态内容和动态渲染,提供了一种方式...

    django开发完美博客

    Django的ORM(对象关系映射)允许开发者用Python代码来操作数据库,无需直接写SQL。 接下来是视图函数,通常在`views.py`中定义。视图负责处理HTTP请求,如GET和POST,根据请求类型和参数执行相应操作,如展示文章...

    Django_layui后台模板

    Django提供了一系列内置功能,如ORM(对象关系映射)、表单处理、认证与授权、URL路由、中间件等,极大地提高了开发效率。 2. Layui框架:Layui是一个采用自身模块规范编写的前端UI框架,其核心特点是轻量、简洁,...

    django model 条件过滤 queryset.filter(**condtions)用法详解

    `queryset.filter(**conditions)`是Django ORM(对象关系映射)中用于筛选和检索数据库记录的重要方法。本篇文章将深入探讨`queryset.filter()`的用法及其相关的条件过滤操作。 首先,`queryset.filter(**...

    详解Django model转字典的几种方法

    在Django框架中,Model是数据库表的抽象表示,它提供了ORM(对象关系映射)功能,使得开发者可以通过Python对象来操作数据库。然而,在实际开发中,有时我们需要将Model对象转换为字典类型,以便于数据传输,比如在...

    Django课件与代码

    通过定义模型类,你可以描述你的数据,并利用Django的ORM(对象关系映射)轻松地操作数据库。在代码中,你将看到如何定义字段、管理选项,以及如何执行CRUD(创建、读取、更新、删除)操作。 视图(View)是处理...

    django-calendar-master_pythondjango_calendar_django_

    在这个项目中,日历的事件数据可能会存储在数据库中,通过 Django 的 ORM(对象关系映射)进行操作。 2. **模型(Model)**:Django 模型定义了数据库表结构,包括字段类型、验证规则等。在这个日历应用中,可能有...

    精通Django.rar

    接着,会深入探讨模型(Model),这是Django的数据层,用于定义数据库结构和业务逻辑。模型字段类型、数据验证、关系管理等都将逐一剖析。此外,还会介绍视图(View)和模板(Template),这是Django的MVT设计模式中...

    Django企业开发实战.源码

    【标签】"Django"进一步确认了这份资料的主题,Django框架在现代Web开发中扮演着重要角色,它提供了丰富的功能,如ORM(对象关系映射)用于数据库操作,内置的管理后台,强大的中间件机制,以及对RESTful API的支持...

Global site tag (gtag.js) - Google Analytics