【4.0】Django框架之ORM创建表关系

【一】表关系的建立

  • 表与表之间的关系

    • 一对一
    • 一对多
    • 多对多
  • 判断表关系的方法

    • 换位思考
book

publish

author

author_detail
  • 图书和出版社是一对多关系
    • 外键字段添加在多的一方,即book
  • 图书和作者是多对多的关系
    • 需要创建第三张表
  • 作者与作者详情表是一对一的关系

图书表

class Book(models.Model):
    # 默认创建主键字段(可忽略不写)
    # 创建字段 :书籍标题
    title = models.CharField(max_length=32, verbose_name="书籍名称")
    # 创建字段 :书籍价格
    # max_digits : 小数一共几位
    # decimal_places :小数点后几位
    price = models.DecimalField(max_digits=8, decimal_places=2, verbose_name="书籍价格")
    '''
    图书和出版社是一对多,并且书是多的一方 , 所以外键字段放在书表里面
    '''
    # to_fields : 默认不写就是和被关联表的id值进行关联
    # on_delete=models.CASCADE : 级联更新
    '''
    如果字段对应的是 ForeignKey 那么 ORM 会自动在字段后面 加 id 变成 publish_id 
    如果自己 加了 id 即 publish_id ,ORM 仍然会帮我们在后面 加 _id 变成 publish_id_id
    
    后面在使用 ForeignKey 时 ,不建议 自己主动加id
    '''
    publish = models.ForeignKey(to='Publisher', on_delete=models.CASCADE)
    '''
    图书和作者是多对多的关系 外键建在任意一方即可 ,但是推荐建在查询频率较高的一方
    '''
    # authors : 是一个虚拟字段,主要是用来告诉 ORM 数据表和作者表是多对多的关系
    # 让 ORM 来帮助我们自动创建第三张表
    authors = models.ManyToManyField(to='Author')

出版社表

class Publisher(models.Model):
    # 默认创建主键字段(可忽略不写)
    # 创建字段 : 出版社名字
    pub_name = models.CharField(max_length=32, verbose_name="出版社名称")
    # 创建字段 : 出版社地址’
    pub_addr = models.CharField(max_length=32, verbose_name="出版社地址")

作者表

class Author(models.Model):
    # 默认创建主键字段(可忽略不写)
    # 创建字段 : 作者名字
    aut_name = models.CharField(max_length=32, verbose_name="作者名字")
    # 创建字段 : 作者年龄
    aut_age = models.IntegerField(verbose_name="作者年龄")
    '''
    作者与作者详情之间是一对一的关系, 外键字段建在任意一方即可,但是推荐建在查询频率较高的一方
    '''
    '''
       如果字段对应的是 OneToOneField 那么 ORM 会自动在字段后面 加 id

       后面在使用 OneToOneField 时 ,不建议 自己主动加id
    '''
    author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)

作者详情表

class AuthorDetail(models.Model):
    # 默认创建主键字段(可忽略不写)
    # 创建字段 : 作者电话
    # 考虑到电话的长度问题,建议用 BigIntegerField 或者 直接 用 CharField存成字符串
    aut_phone = models.BigIntegerField(verbose_name="作者电话")
    # 创建字段 : 作者的住址
    aut_addr = models.CharField(max_length=32, verbose_name="作者住址")

配置文件:settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'day10', # 指定数据库
        'USER': 'root', #  自己的用户名
        'PASSWORD': '1314521',  #  自己的密码
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'CHARSET': 'utf8',
    }
}

初识化文件:__init__.py

import pymysql

pymysql.install_as_MySQLdb()

终端重载数据库

python39 manage.py makemigrations
python39 manage.py migrate

【二】总结

(1)ForeignKey 多对一

  • 是Django中的一个字段类型,用于建立模型间的多对一关系。通过在一个模型中使用ForeignKey字段,可以将其与另一个模型的主键关联起来,表示多个实例对应一个实例的关系。
  • 比如
    • 一个博客系统中,可以有两个模型:作者(Author)和文章(Post)
    • 一个作者可以写多篇文章,但一篇文章只能对应一个作者。
    • 这时,可以在Post模型中定义一个ForeignKey字段,指向Author模型:
class Author(models.Model):
    name = models.CharField(max_length=50)

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

(2)ManyToManyField 多对多

  • 也是Django中的一个字段类型,用于建立模型间的多对多关系。
    • 通过使用ManyToManyField字段,可以在两个模型之间创建一个多对多的关联,表示多个实例之间互相对应的关系。
  • 继续以博客系统为例
    • 在一个标签(Tag)模型和文章(Post)模型之间存在多对多的关系
    • 一篇文章可以对应多个标签,一个标签也可以对应多篇文章。
    • 这时,可以在Post模型和Tag模型中分别定义ManyToManyField字段:
class Tag(models.Model):
    name = models.CharField(max_length=50)

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    tags = models.ManyToManyField(Tag)

(3)OneToOneField 一对一

  • 是Django中的另一个字段类型,用于建立模型间的一对一关系。
    • 通过使用OneToOneField字段,可以在两个模型之间创建一个一对一的关联,表示一个实例对应另一个实例的关系。
  • 例如
    • 一个用户(User)模型和一个用户资料(Profile)模型之间有一对一的关系
    • 每个用户只有一个对应的用户资料。
    • 可以在Profile模型中定义一个OneToOneField字段,在User模型上进行关联:
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField()
    location = models.CharField(max_length=50)
  • 上述代码中,Profile模型中的user字段是一个OneToOneField字段,它以User模型为参数来指定一对一的关联。这
  • 样就可以让每个User实例对应一个Profile实例,方便扩展用户信息。

(4)ManyToManyFieldOneToOneField自动加id后缀

 '''
 如果字段对应的是 ForeignKey/OneToOneField 那么 ORM 会自动在字段后面 加 id 变成 publish_id 
 如果自己 加了 id 即 publish_id ,ORM 仍然会帮我们在后面 加 _id 变成 publish_id_id

 后面在使用 ForeignKey/OneToOneField 时 ,不建议 自己主动加id
 '''
  • 实际上,ManyToManyFieldOneToOneField字段在数据库中会自动创建相关的外键
    • 并非在字段名后加上'id'后缀。
    • 这些外键字段名的生成方式取决于Django的命名规则和相关模型的名称。

对于ManyToManyField字段,Django会默认使用源模型(即声明ManyToManyField的模型)的名称和目标模型(关联的模型)的名称来生成中间表的名称,并在其中创建外键。

  • 例如,假设存在两个模型:AuthorBook,并且在Author模型中有一个books字段声明为ManyToManyField类型:
class Author(models.Model):
    name = models.CharField(max_length=50)
    books = models.ManyToManyField(Book)
  • Django将在数据库中创建一个名为author_books的中间表,并包含两个外键字段:
    • author_idbook_id

对于OneToOneField字段,Django会根据源模型(即声明OneToOneField的模型)的名称和目标模型(关联的模型)的名称生成外键字段的名称。

  • 例如,假设存在两个模型:
    • UserProfile
  • 并在Profile模型中有一个user字段声明为OneToOneField类型:
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField()
    location = models.CharField(max_length=50)
  • Django将在Profile模型中创建一个名为user_id的外键字段,用于与User模型进行关联。

总结来说,ManyToManyFieldOneToOneField字段在数据库中会生成相关的外键字段,并没有自动加上'id'后缀。

其他与这些字段相关的命名规则和约定主要取决于使用Django的默认行为或者通过特定参数进行自定义。

【三】小结

  • 在Django 1.x 版本中外键默认都是级联更新删除的
  • 在多对多表关系中,不止以上一种创建方式,这只介绍其中的一种
  • 针对外键里面的其它参数,后面会详细讲解
posted @ 2023-07-17 11:28  Chimengmeng  阅读(78)  评论(0编辑  收藏  举报