美文网首页django
django-model外键关系之一对多

django-model外键关系之一对多

作者: 陆_志东 | 来源:发表于2018-08-22 21:53 被阅读520次

    一对多

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

    比如,一辆汽车(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='john@example.com')
    >>> r.save()
    
    >>> r2 = Reporter(first_name='Paul', last_name='Jones', email='paul@example.com')
    >>> 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: John Smith>
    
    # 注意,将对象分配给一个外键之前必须保存。例如,使用未保存的Reporter 创建Article 将引发ValueError:
    >>> r3 = Reporter(first_name='John', last_name='Smith', email='john@example.com')
    >>> Article(headline="This is a test", pub_date=date(2005, 7, 27), reporter=r3)
    Traceback (most recent call last):
    ...
    ValueError: 'Cannot assign "<Reporter: John Smith>": "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='john@example.com')
      >>> 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='john@example.com')
      >>> 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='john@example.com')
      >>> 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='john@example.com')
      >>> 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外键关系之一对多

        本文链接:https://www.haomeiwen.com/subject/seqeiftx.html