Django Related objects

在使用django时,在模型定义的关系中,如果使用到了ForeignKey, OneToOneField, 或者 ManyToManyField,那么该模型的实例,就有了便捷的API去访问相关的对象。

使用的模型:

from django.db import models
class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    # On Python 3: def __str__(self):
    def __unicode__(self):
        return self.name
class Author(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField()

    # On Python 3: def __str__(self):
    def __unicode__(self):
        return self.name
class Entry(models.Model):
    blog = models.ForeignKey(Blog)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateField()
    mod_date = models.DateField()
    authors = models.ManyToManyField(Author)
    n_comments = models.IntegerField()
    n_pingbacks = models.IntegerField()
    rating = models.IntegerField()

    # On Python 3: def __str__(self):
    def __unicode__(self):
        return self.headline


1、外键的便捷API

    例如:

>>> e = Entry.objects.get(id=2)
>>> e.blog  # 通过这种方式,就能获取到外键blog对象

    如果你想改变关联的外键,也很简单,如:

 >>> e = Entry.objects.get(id=2)
 >>> e.blog = Blog()
 >>> e.save()  # 这一步是必须的,只有调用了save后,才会将改变的结果更新到数据库

    如果在定义外键时,设置null=True,则还可以这么写:e.blog=None

    注:Forward access to one-to-many relationships is cached the first time the related object is accessed. Subsequent accesses to the foreign key on the same object instance are cached.

    如:

 >>> e = Entry.objects.get(id=2)
 >>> print(e.blog)  # Hits the database to retrieve the associated Blog.
 >>> print(e.blog)  # Doesn't hit the database; uses cached version.

    select_related()方法,获取实例所有相关的模型对象,并缓存起来,在通过外键关系、一对多关系访问对象时,不会再造成数据库访问。

    如果一个模型含有外键,该模型的外键的实例对象就有访问Manager管理器的权限,默认情况下,这个管理器的名字是xxx_set, xxx是外键模型名称的小写;这个Manager会返回一个QuerySets,这个QuerySets可以像其他的QuerySet一样,使用各种方法进行操作,如filter()等。

如:

>>> b = Blog.objects.get(id=1)
>>> b.entry_set.all() # 返回所有和当前Blog有关联的Entry的集合

# b.entry_set 是一个包含了QuerySet的Manager模型管理器
>>> b.entry_set.filter(headline__contains='Lennon')
>>> b.entry_set.count()

    同样的,你也可以设置xxx_set的访问名称,通过在定义外键时,加上related_name,like this :blog=models.Foreign(Blog, related_name='entries'),那么代码就成了这样:

>>> b = Blog.objects.get(id=1)
>>> b.entries.all() # 返回所有和当前Blog有关联的Entry的集合

    另外,对于上面提到的QuerySet还有如下一些方法,可供使用,如add()、create()、remove()、clear()等。

2、Many-to-many 关系

    和外键约束类似,处理many-to-many关系,在后台处理上是去维护两个一对多的关联关系,这两个一对多的关系在访问上不同的是:定义了多对多关系属性的模型对象,通过属性直接访问,被关联的模型在访问时,就要使用:小写的模型名称_set的方式进行访问(这里和外键是一样的访问方式);如下:

e = Entry.objects.get(id=3)
e.authors.all() # 返回所有Entry关联的素有Author
e.authors.count()
e.authors.filter(name__contains='John')

a = Author.objects.get(id=5)
a.entry_set.all() # 返回Author所有关联的Entry

    同样的,many-to-many关联关系同样可以通过related_name来指定访问名称。

3、one-to-one关系

    如下:

class EntryDetail(models.Model):
    entry = models.OneToOneField(Entry)
    details = models.TextField()
ed = EntryDetail.objects.get(id=2)
ed.entry # Returns the related Entry object.

    在访问‘反转’模型的方式上唯一不同的是:一对一返回的是一个实例对象,而非结果集,所以,对应的'反转'模型就有一个模型名称对应的属性(全小写),如下:

e = Entry.objects.get(id=2)
e.entrydetail # returns the related EntryDetail object

    注:If no object has been assigned to this relationship, Django will raise a DoesNotExist exception.

4、关联关系上的查询

    涉及到相关关系查询时,其查询规则和普通查询类似,当指定查询条件时。可以是主键值或者实例对象;如:

Entry.objects.filter(blog=b) # Query using object instance
Entry.objects.filter(blog=b.id) # Query using id from instance
Entry.objects.filter(blog=5) # Query using id directly


你可能感兴趣的:(Django Related objects)