django-model外键关系之一对多

一对多

外键字段是放在多的一方模型类里面的

比如,一辆汽车(Car)有一个制造商(Manufacturer) —— 但是一个制造商(Manufacturer) 生产很多汽车(Car),每一辆汽车(Car) 只能有一个制造商(Manufacturer) —— 使用下面的定义:

from django.db import models

class Manufacturer(models.Model):
    # ...
    pass

class Car(models.Model):
    company_that_makes_it = models.ForeignKey(Manufacturer)

如果想要创建和自己关联的一对多关系,使用self指向自己

models.ForeignKey('self')

一对多的使用和绑定

准备数据

比如有下面两个模型类

from django.db import models

class Reporter(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    email = models.EmailField()

    def __str__(self):              # __unicode__ on Python 2
        return "%s %s" % (self.first_name, self.last_name)

class Article(models.Model):
    headline = models.CharField(max_length=100)
    pub_date = models.DateField()
    reporter = models.ForeignKey(Reporter)

    def __str__(self):              # __unicode__ on Python 2
        return self.headline

    class Meta:
        ordering = ('headline',)

关联对象

默认方式

# 创建几个Reporter:
>>> r = Reporter(first_name='John', last_name='Smith', email='[email protected]')
>>> r.save()

>>> r2 = Reporter(first_name='Paul', last_name='Jones', email='[email protected]')
>>> r2.save()
#创建一个Article:
>>> from datetime import date
>>> a = Article(id=None, headline="This is a test", pub_date=date(2005, 7, 27), reporter=r)
>>> a.save()

>>> a.reporter.id
1

>>> a.reporter


# 注意,将对象分配给一个外键之前必须保存。例如,使用未保存的Reporter 创建Article 将引发ValueError:
>>> r3 = Reporter(first_name='John', last_name='Smith', email='[email protected]')
>>> Article(headline="This is a test", pub_date=date(2005, 7, 27), reporter=r3)
Traceback (most recent call last):
...
ValueError: 'Cannot assign "": "Reporter" instance isn't saved in the database.'

#访问关联对象,具体看模型的查询
>>> r = a.reporter
>>> r.first_name, r.last_name
('John', 'Smith')

除了上面的方式外还有几个内建的关联对象的方法,add,create,remove,clear

  • add(obj1, obj2, ...)添加一指定的模型对象到关联的对象集中。
    >>> r1 = Reporter(first_name='John', last_name='Smith', email='[email protected]')
    >>> r1.save()
    >>> a1 = Article(id=None, headline="This is a test", pub_date=date(2005, 7, 27))
    >>> a1.save()
    >>> r1.article_set.add(a1)

  • create(**kwargs)创建一个新的对象,将它保存并放在关联的对象集中。返回新创建的对象。
    >>> r1 = Reporter(first_name='John', last_name='Smith', email='[email protected]')
    >>> r1.save()
    >>> r1.article_set.create(headline="This is a test", pub_date=date(2005, 7, 27))

  • remove(obj1, obj2, ...)从关联的对象集中删除指定的模型对象。
    >>> r1 = Reporter(first_name='John', last_name='Smith', email='[email protected]')
    >>> r1.save()
    >>> r1.article_set.create(headline="This is a test", pub_date=date(2005, 7, 27))
    >>> a1 = Article.objects.filter(id=1)
    >>> r1.article_set.remove(a1)

  • clear()从关联的对象集中删除所有的对象。
    >>> r1 = Reporter(first_name='John', last_name='Smith', email='[email protected]')
    >>> r1.save()
    >>> r1.article_set.create(headline="This is a test", pub_date=date(2005, 7, 27))
    >>> r1.article_set.clear()

  • 一次性关联多个对象
    若要一次性给关联的对象集赋值,只需要给它赋值一个可迭代的对象。这个可迭代的对象可以包含对象的实例,或者一个主键值的列表。
    >>> r1 = Reporter.objects.get(id=1)
    >>> r1.entry_set = [a1, a2]
    a1 和a2 可以是Article 实例,也可以是Article实例主键的整数值。

外键关联对象的查找(或者说是索引也可以说是获取)或者说是关联模型的反向查询

比如有两个模型类A和B,A是多的一方,B是一的一方,外键字段是设置在多的一方里面的

  • 使用默认方式(源模型名__set方式) 源模型名要小写

    class A(models.Model):
    age = models.IntField()
    obj_b = models.ForeignKey(B)

    class B(modes.Model):
    name = models.CharField()
    pass

    b1 = B()
    b1.save()
    a1 = A(b=b1)
    a1.save()
    那么a拿到b的对象
    a1.obj_b.name 就能拿到了 a对象绑定的b对象的name字段值
    那么b怎么拿到a 呢 使用源模型名(小写)__set方法
    b1.a_set.age b就拿到了关联的a对象的age字段值

  • 使用related_name属性(覆盖上面的默认方式)

    class A(models.Model):
    age = models.IntField()
    obj_b = models.ForeignKey(B,related_name="obj_a")

    class B(modes.Model):
    name = models.CharField()
    pass

    b1 = B()
    b1.save()
    a1 = A(b=b1)
    a1.save()
    a拿到b的方式还是一样的
    a1.obj_b.name 就能拿到了 a对象绑定的b对象的name字段值
    b拿到a 的方式变了,不在是源模型名__set,而是related_name指定的值
    b1.obj_a.age b1就拿到了关联的a1对象的age字段值

你可能感兴趣的:(django-model外键关系之一对多)