Django文档——Model中的ForeignKey,ManyToManyField与OneToOneField

ForeignKey,ManyToManyField与OneToOneField分别在Model中定义多对一,多对多,一对一关系。

例如,一本书由一家出版社出版,一家出版社可以出版很多书。一本书由多个作者合写,一个作者可以写很多书。

class Author(models.Model):

name=models.CharField(max_length=20)

class Publisher(models.Model):

name=models.CharField(max_length=20)

class Book(models.Model):

name=models.CharField(max_length=20)

pub=models.ForeignKey(Publisher)

authors=models.ManyToManyField(Author)

1.接洽关系尚不决义的Model

若是你要与某个尚不决义的 model 建树接洽关系 ,就应用 model 的名称,而不是应用 model 对象本身。

例子中,若是Publisher与Author在Book后面定义,须要写成下面的情势:

class Book(models.Model):

name=models.CharField(max_length=20)

pub=models.ForeignKey(""Publisher"")

authors=models.ManyToManyField(""Author"")

2.Model接洽关系自身

Model可以与自身做多对一关系

class People(models.Model):

name=models.CharField(max_length=20)

leader=models.ForeignKey(""self"",blank=True,null=True)

Model也可以与自身做多对多关系

class Person(models.Model):

friends = models.ManyToManyField("self")

默认景象下,这种接洽关系关系是对称的,若是Person1是Person2的伴侣,那么Person2也是Person1的伴侣

p1=Person()

p1.save()

p2=Person()

p2.save()

p3=Person()

p3.save()

p1.friends.add(p2,p3)

上述景象下,要查找p3的伴侣,不消p3.person_set.all(),而直接用p3.friends.all()就可以了

若是想作废这种对称关系,将symmetrical设为False

class Person2(models.Model):

friends=(models.ManyToManyField("self",symmetrical=False)

如许查询p3的伴侣,就须要p3.person_set.all()了

3.反向名称related_name

反向名称,用来从被接洽关系字段指向接洽关系字段。

重视,在你定义 抽象 model (abstract models) 时,你必须显式指定反向名称; 只有在你这么做了之后, 某些希罕语法 (some special syntax) 才干正常应用。

class Book(models.Model):

name=models.CharField(max_length=20)

pub=models.ForeignKey(Publisher,related_name=""pub"")

authors=models.ManyToManyField(Author,related_name=""author"")

如许用Publisher或者Author反向查询Book时可以用related_name了:publisher1.pub.all()或者author1.author.all()。

若是不想设置反向关系,设置related_name为”“+”“或者以”“+”“停止。

user = models.ForeignKey(User, related_name=”“+”“)

若是有多个ManyToManyField指向同一个Model,如许反向查询FOO_set的时辰就无法弄清是哪个ManyToManyField字段了,可以禁止反向关系:

users = models.ManyToManyField(User, related_name=”“u+”“)

referents = models.ManyToManyField(User, related_name=”“ref+”“)

4.数据库发挥解析 (Database Representation)

多对一:Django 应用ForeignKey字段名称+ “_id” 做为数据库中的列名称。在上方的例子中,BOOK model 对应的数据表中会有 一个 publisher_id 列。

你可以经由过程显式地指定 db_column 来改变该字段的列名称,不过,除非你想自定 义 SQL ,不然没须要更改数据库的列名称。

多对多:Django 创建一个中心表来默示ManyToManyField关系。默认景象下,中心表的名称由两个关系表名连络而成。

因为某些数据库对表名的长度有限制,所以中心表的名称会主动限制在64个字符以内,并包含一个不反复的哈希字符串。这

意味着,你可能看到类似 book_authors_9cdf4 如许的表名称。你可以应用 db_table 选项手动指定中心表名称。

然则,若是你想手动指定中心表,你可以用 through 选项来指定model 应用别的某个 model 来经管多对多关系。而这个 model 就是中心表所对应的 model :

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了。

要建树Person与Group的关系就不克不及用add,create,remove了,而是须要经由过程Membership进行。

ringo = Person.objects.create(name=”Ringo Starr”)

paul = Person.objects.create(name=”Paul McCartney”)

beatles = 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()

clear()还是可以应用的

beatles.members.clear()

当多对多关系接洽关系自身时,中心表的ForeignKey是可以指向同一个Model的,然则它们必须被看做ManyToManyField的两边,而不是对称的,须要设置 symmetrical=False。

5.其它参数 (Arguments)

5.1 ForeignKey 接管下列这些可选参数,这些参数定义了关系是如何运行的。

ForeignKey.limit_choices_to

它是一个包含筛选前提和对应值的字典,用来在 Django 经管后台筛选 接洽关系对象。例如,哄骗 Python 的 datetime 模块,过滤掉不合适筛选前提接洽关系对象:

limit_choices_to = {“”pub_date__lte”“: datetime.date.today}

只有 pub_date 在当前日期之前的接洽关系对象才容许被选。

也可以应用 Q 对象来庖代字典,从而实现更错杂的筛选。当limit_choices_to为Q对象时,若是把此外键字段放在ModelAdmin的raw_id_fields时是不成用的。

ForeignKey.to_field

指定当前关系与被接洽关系对象中的哪个字段接洽关系。默认景象下,to_field 指向被接洽关系对象的主键。

ForeignKey.on_

当一个model对象的ForeignKey接洽关系的对象被删除时,默认景象下此对象也会一路被级联删除的。

user = models.ForeignKey(User, blank=True, null=True, on_=models.CASCADE)

CASCADE:默认值,model对象会和ForeignKey接洽关系对象一路被删除

SET_NULL:将model对象的ForeignKey字段设为null。当然须要将null设为True。

SET_DEFAULT:将model对象的ForeignKey字段设为默认值。

Protect:删除ForeignKey接洽关系对象时会生成一个ProtectedError,如许ForeignKey接洽关系对象就不会被删除了。

SET():将model对象的ForeignKey字段设为传递给SET()的值。

def get_sentinel_user():

return User.objects.get_or_create(username=""d"")[0]

class MyModel(models.Model):

user = models.ForeignKey(User, on_=models.SET(get_sentinel_user))

DO_NOTHING:啥也不做。

5.2 ManyToManyField 接管下列可选参数,这些参数定义了关系是如何运行的。

ManyToManyField.limit_choices_to

和 ForeignKey.limit_choices_to 用法一样。

limit_choices_to 对于经由过程 through 参数指定了中介表的 ManyToManyField 不起感化。

ManyToManyField.symmetrical

只要定义递归的多对多关系时起感化。

ManyToManyField.through

手动指定中心表

ManyToManyField.db_table

指定命据库中保存多对多关系数据的表名称。若是没有供给该选项,Django 就会按照两个关系表的名称生成一个新的表名,做为中心表的名称。

6.OneToOneField

class OneToOneField(othermodel[, parent_link=False, **options])

用来定义一对一关系。笼统地讲,它与声了然 unique=True 的 ForeignKey 很是类似,不合的是应用反向接洽关系的时辰,获得的不是一个对象列表,而是一个零丁的对象。

在某个 model 扩大自另一个 model 时,这个字段是很是有效的;例如: 多表持续 (Multi-tableinheritance) 就是经由过程在子 model 中添加一个指向父 model 的一对一接洽关系而实现的。

必须给该字段一个参数:被接洽关系的 model 类。工作体式格式和 ForeignKey 一样,连递归接洽关系 (recursive) 和 延后接洽关系 (lazy) 都一样。

此外,OneToOneField 接管 ForeignKey 可接管的参数,只有一个参数是 OnetoOneField 专有的:OneToOneField.parent_link

若是为 True ,并且感化于持续自某个父 model 的子 model 上(这里不克不及是延后持续,父 model 必须真实存在 ),那么该字段就会变成指向父类实例的引用(或者叫链接),

而不是象其他OneToOneField 那样用于扩大父类并持续父类属性。

django.db import models, transaction, IntegrityError

class Place(models.Model):

name = models.CharField(max_length=50)

address = models.CharField(max_length=80)



def __unicode__(self):

    return u"%s the place" % self.name

class Restaurant(models.Model):

place = models.OneToOneField(Place, primary_key=True)

serves_hot_dogs = models.BooleanField()

serves_pizza = models.BooleanField()



def __unicode__(self):

    return u"%s the restaurant" % self.place.name

class Waiter(models.Model):

restaurant = models.ForeignKey(Restaurant)

name = models.CharField(max_length=50)



def __unicode__(self):

    return u"%s the waiter at %s" % (self.name, self.restaurant)

应用反向接洽关系的时辰,获得的不是一个对象列表,而是一个零丁的对象:

p1 = Place(name=”“Demon Dogs”“, address=”“944 W. Fullerton”“)

p1.save()

r = Restaurant(place=p1, serves_hot_dogs=True, serves_pizza=False)

r.save()

p1.restaurant

Place.objects.get(restaurant__place__name__startswith=”Demon”)

Waiter.objects.filter(restaurant__place__name__startswith=”Demon”)

思想的伟大不在于能否容纳琐碎小事,而在于能否用自己的影响使小事变成大事。对小事漠不关心的人也不会对大事真正感兴趣。 ——罗斯金

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值