zoukankan      html  css  js  c++  java
  • Django 06. django框架模型之表关系ForeignKey,ManyToManyField与OneToOneField


    简介
           数据库中表与表之间的关系,举例详解一对多、一对一、多对多关系,及表关系一些进阶技巧。

    1. 数据库中表与表之间的关系 
     
      • 一对多,models.ForeignKey(ColorDic)
      • 一对一,models.OneToOneField(OneModel)
      • 多对多,authors = models.ManyToManyField(Author)

    应用场景:

        • 一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了)。
          例如:与同事合作开发过程中两人都用到一某个表,这个表原有含10列数据,经过一段时间之后,发现10列无法满足自己的需求,需要为原来的表再添加5列数据,但是为了不影响同事的使用,可以使用一对一关系设计表,新的表中只需要包含要新加的这5列数据即可。

        • 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)。
          例如:创建用户信息时候,用户信息中包含用户类型(普通用户、管理员、超级管理员),用户与用户类型就属于一对多关系。一个用户对应一种用户类型,但一种用户类型可以包含多个用户。

        • 多对多:在某表中创建一行数据时,有一个可以多选的下拉框。
          例如:创建用户信息,需要用户选择爱好,一个用户可以有多个爱好,一种爱好可以被多个用户选择。

    2. 举例详解
        例如,一本书由一家出版社出版,一家出版社可以出版很多书。一本书由多个作者合写,一个作者可以写很多书。
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    from __future__ import unicode_literals
    from django.db import models
     
    class Author(models.Model):
        name = models.CharField(max_length=30)
     
    class Publisher(models.Model):
        name = models.CharField(max_length=50)
     
    class Book(models.Model):
        name = models.CharField(max_length=50)
        #一本书由一家出版社发布,一个出版社发布多本书。属于一对多关系,用ForeignKey()
        pub = models.ForeignKey(Publisher)
        #一本书可以由多个作者合写,一个作者可以写多本书,属于多对多关系,用ManyToManyField
        authors = models.ManyToMany(Author)
        生成结果:
        
     一共生成了4张表:
     
    web_author(作者表)


     web_publisher(出版社表)

     
    web_book_authors(记录book与author多对多关系表。多对多关系要借助第三张表建立关系)

     
    web_book(book表,其中pub_id体现书与出版社之间的一对多关系)


    3. 表关系进阶

    1. 关联尚未定义的Model
     
    class Book(models.Model):
        name = models.CharField(max_length = 50)
        #如果Publisher与Author在Book后面定义,需要使用model 的名称,而不是使用 model 对象本身
        pub = models.ForeignKey('Publisher')
        authors = models.ManyToManyField('Author')
        
    class Publisher(models.Model):
        name = models.CharField(max_length = 50)
     
    class Author(models.Model):
        name = models.CharField(max_length = 30)

    2. Model关联自身
    1) Model可以与自身做多对一关系
     
    class People(models.Model):
        name = models.CharField(max_length = 30)
        leader = models.ForeignKey('self', blank=True, null=True)
     
            说明:一个领导有多个下属,一个下属对应一个直接领导,同时领导也是领导的下属。就属于多对一关系,且需要与自身做多对一关系。且注            意,设计这表时要设置blank=True和null=True.
           
           2) Model可以与自身做多对多关系
            
            class Person(models.Model):
                friends = models.ManyToManyField('self')
            
                    说明:1. 你是我的朋友,我可以有多个朋友,我也是你的朋友,你也可以有多个朋友,这就属于朋友间的多对多关系。
                               2. 会生成两张表,一张person表,只含有id和name。一张person_friends表含有id,from_person_id,to_person_id
                                person_friends:
                                   
            

            3. 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 那样用于扩展父类并继承父类属性。
     
    from 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
    <Restaurant: Demon Dogs the restaurant>
    >>> Place.objects.get(restaurant__place__name__startswith="Demon")
    <Place: Demon Dogs the place>
    >>> Waiter.objects.filter(restaurant__place__name__startswith="Demon")
     
  • 相关阅读:
    2020 年最棒的 9 个 Java 框架,哪个最香?
    CTO:不要在 Java 代码中写 set/get 方法了,逮一次罚款
    面试常考:Java中synchronized和volatile有什么区别?
    树莓派3B装ubuntu server后开启wifi
    转:程序内存空间(代码段、数据段、堆栈段)
    环境变量IFS
    python之格式化字符串速记整理
    logging模块简单用法
    理解正则表达式的匹配关系
    cut和tr命令的联合使用
  • 原文地址:https://www.cnblogs.com/PythonHomePage/p/7634394.html
Copyright © 2011-2022 走看看