Django(part34)--一对多映射

学习笔记,仅供参考



数据表关联关系映射


一对多映射


一对多是表示现实事物间存在的一对多的对应关系。比如,一个学生只能属于一个班级,一个班级可以有多个学生;一本图书只能属于一个出版社,一个出版社允许出版多本书。


  • 语法

一个A类对象可以关联多个B类对象

class A(model.Model):
    pass

class B(model.Model):
    属性 = models.ForeignKey(A模型类, ...)

外键关联ForeignKey


构造函数
ForeignKey(to, on_delete, **options)
  • 参数

on_delete

models.CASCADE 
#级联删除,若设置此参数值,则当主对象被删除时,同时删除与其关联的从属对象。
models.PROTECT 
#如果主对象存在关联对象时,我们删除主对象,就会抛出ProtectedError以阻止其被删除;
SET_NULL 
#当删除主对象时,从属对象指向null
SET_DEFAULT 
#将ForeignKey设置为其默认值;必须设置ForeignKey的默认值。

**options是常用的字段选项

null
unique
#等等

举个例子


  • 定义一对多类

models.py

from django.db import models

# Create your models here.

class Publisher(models.Model):
    name = models.CharField("出版社名", max_length = 50,null = True)
    booknumber = models.PositiveIntegerField("初版书籍总量", default = 0)
    tele = models.CharField("联系电话", max_length = 11, null = False)
    class Meta:
        db_table = "china_publisher"
        verbose_name = "ChinaPublisher"
        verbose_name_plural  = "ChinaPublishers"
    def __str__(self):
        string = "出版社:%s" % (self.name)
        return string

class Book(models.Model):
    title = models.CharField("书名", max_length = 30)
    exfacPrice = models.DecimalField("出厂价", 
                                   max_digits = 6, decimal_places = 2,
                                   default = 0)
    
    price = models.DecimalField("售价", 
                              max_digits = 6, decimal_places = 2,
                              default = 0)
    pub = models.ForeignKey(Publisher, on_delete = models.CASCADE , null=True)
    
    def __str__(self):
        string = "书名:%s" % (self.title) 
        return string

  • 创建一对多的对象

打开Django shell,敲入如下代码:

from bookstore import models
pub1 = models.Publisher.objects.create(name='中国人民大学出版社', tele = "62511329", booknumber = 22000)
models.Book.objects.create(title='统计学', pub=pub1)
models.Book.objects.create(title='多元统计分析', pub=pub1)
models.Book.objects.create(title='回归分析', pub=pub1)

pub2 = models.Publisher.objects.create(name='高等教育出版社', tele = "82080802", booknumber = 12000)
models.Book.objects.create(title='数学分析', pub=pub2)
models.Book.objects.create(title='高等代数', pub=pub2)

  • 查询

通过多查一:

#通过一本书找到对应的出版社
abook = models.Book.objects.get(title='统计学')
print(abook.title, '的出版社是:', abook.pub.name)

输出:

In [2]: abook = models.Book.objects.get(title='统计学')
   ...: print(abook.title, '的出版社是:', abook.pub.name)
   ...:
统计学 的出版社是: 中国人民大学出版社

通过一查多:

#通过出版社查询对应的书
pub1 = models.Publisher.objects.get(name='中国人民大学出版社')
books = pub1.book_set.all()  
#通过book_set获取pub1对应的多个Book对象
#相当于
#books = models.Book.objects.filter(pub=pub1)  
print("清华大学出版社的书有:")
for book in books:
    print(book.title)

输出:

In [3]: #通过出版社查询对应的书
   ...: pub1 = models.Publisher.objects.get(name='中国人民大学出版社')
   ...: books = pub1.book_set.all()
   ...: #通过book_set获取pub1对应的多个Book对象
   ...: #相当于
   ...: #books = models.Book.objects.filter(pub=pub1)
   ...: print("清华大学出版社的书有:")
   ...: for book in books:
   ...:     print(book.title)
   ...:
清华大学出版社的书有:
统计学
多元统计分析
回归分析

我们看一下mywebdb数据库中china_publisher数据表:

mysql> select * from china_publisher;
+----+--------------------+------------+----------+
| id | name               | booknumber | tele     |
+----+--------------------+------------+----------+
|  1 | 中国人民大学出版社 |      22000 | 62511329 |
|  2 | 高等教育出版社     |      12000 | 82080802 |
+----+--------------------+------------+----------+
2 rows in set (0.00 sec)

再看一下mywebdb数据库中bookstore_book数据表:

mysql> select * from bookstore_book;
+----+-------------------+------------+-------+--------+
| id | title             | exfacPrice | price | pub_id |
+----+-------------------+------------+-------+--------+
|  1 | Djangoweb开发实战 |       0.00 |  0.00 |   NULL |
|  2 | python            |       0.00 |  0.00 |   NULL |
|  3 | R                 |       0.00 |  0.00 |   NULL |
|  5 | 算法              |       0.00 |  0.00 |   NULL |
|  6 | 集体智慧编程      |       0.00 |  0.00 |   NULL |
|  8 | 统计学            |       0.00 |  0.00 |      1 |
|  9 | 多元统计分析      |       0.00 |  0.00 |      1 |
| 10 | 回归分析          |       0.00 |  0.00 |      1 |
| 11 | 数学分析          |       0.00 |  0.00 |      2 |
| 12 | 高等代数          |       0.00 |  0.00 |      2 |
+----+-------------------+------------+-------+--------+
10 rows in set (0.01 sec)

bookstore_book数据表的pub_id字段关联了china_publisher数据表中的id字段,所以pub_id=1表示中国人民大学出版社pub_id=2表示高等教育出版社


最后,我们启动服务,并向http://127.0.0.1:8000/admin/bookstore/book/发起请求:

点击高等代数:

可以看到,在高等代数的记录中,pub默认为高等教育出版社,但是它有一个可选框,我们可以在中国人民大学出版社高等教育出版社之间选择。

现在,我们将高等代数的出版社改为中国人民大学出版社,并点击保存。

现在,查看我们的bookstore_book数据表:

mysql> select * from bookstore_book;
+----+-------------------+------------+-------+--------+
| id | title             | exfacPrice | price | pub_id |
+----+-------------------+------------+-------+--------+
|  1 | Djangoweb开发实战 |       0.00 |  0.00 |   NULL |
|  2 | python            |       0.00 |  0.00 |   NULL |
|  3 | R                 |       0.00 |  0.00 |   NULL |
|  5 | 算法              |       0.00 |  0.00 |   NULL |
|  6 | 集体智慧编程      |       0.00 |  0.00 |   NULL |
|  8 | 统计学            |       0.00 |  0.00 |      1 |
|  9 | 多元统计分析      |       0.00 |  0.00 |      1 |
| 10 | 回归分析          |       0.00 |  0.00 |      1 |
| 11 | 数学分析          |       0.00 |  0.00 |      2 |
| 12 | 高等代数          |       0.00 |  0.00 |      1 |
+----+-------------------+------------+-------+--------+
10 rows in set (0.00 sec)

很好!记录已经被更新!

猜你喜欢

转载自blog.csdn.net/m0_37422217/article/details/106894606