文章链接:wupeiqi
连表
class UserProfile(models.Model):
user_info = models.OneToOneField('UserInfo')
username = models.CharField(max_length=64)
password = models.CharField(max_length=64)
def __unicode__(self):
return self.username
class UserInfo(models.Model):
user_type_choice = (
(0, u'普通用户'),
(1, u'高级用户'),
)
user_type = models.IntegerField(choices=user_type_choice)
name = models.CharField(max_length=32)
email = models.CharField(max_length=32)
address = models.CharField(max_length=128)
def __unicode__(self):
return self.name
class UserGroup(models.Model):
caption = models.CharField(max_length=64)
user_info = models.ManyToManyField('UserInfo')
def __unicode__(self):
return self.caption
class Host(models.Model):
hostname = models.CharField(max_length=64)
ip = models.GenericIPAddressField()
user_group = models.ForeignKey('UserGroup')
def __unicode__(self):
return self.hostname
一对多:models.ForeignKey(其他表)
多对多:models.ManyToManyField(其他表)
一对一:models.OneToOneField(其他表)
应用场景:
一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)
例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。
多对多:在某表中创建一行数据是,有一个可以多选的下拉框
例如:创建用户信息,需要为用户指定多个爱好
一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了
例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据
一对一 OneToOneField(ForeignKey)
例:
# 一个用户关联唯一的blog
class UserInfo(AbstractUser):
blog = models.OneToOneField(to="Blog", to_field="nid", null=True, on_delete=models.DO_NOTHING)
###### 对于一对一 ######
# 1. 一对一其实就是 一对多 + 唯一索引
# 2.当两个类之间有继承关系时,默认会创建一个一对一字段
# 如下会在A表中额外增加一个c_ptr_id列且唯一:
class C(models.Model):
nid = models.AutoField(primary_key=True)
part = models.CharField(max_length=12)
class A(C):
id = models.AutoField(primary_key=True)
code = models.CharField(max_length=1)
一对多关系表设计
在“多”方设置外键(foreign key),关联父表(主表)的主键。
class School(models.Model):
school_name = models.CharField(max_length=20)
school_address = models.CharField(max_length=50)
class Student(models.Model):
name = models.CharField(max_length=10)
sex = models.CharField(max_length=10)
score = models.FloatField()
# Django2.0 必须添加on_delete=models.CASCADE,级联删除
school = models.ForeignKey(to="School", on_delete=models.CASCADE)
#添加学校记录:
school1 = School(school_name='清华大学',school_address='北京')
school1.save()
或者
School.objects.create(school_name='南开大学',school_address='天津')
#添加学生记录(要进行关联学校记录)
#通过学校的实例化对象关联
stu4 = Student(name="李红",sex='女',score=82,school=school1)
stu4.save()
#通过学生的外键列名关联学校的id
stu4 = Student(name="李红",sex='女',score=82,school_id=24)
stu4.save()
#查询学校编号为23或25的学生记录。
Student.objects.filter(school_id__in =(23,25))
#查询学号大于9的学生记录
results = Student.objects.filter(id__gt =9) # 查询出的是QuerySet对象
for stu in results:
print(stu.name)
多对多 ManyToManyField(RelatedField)
"多对多"关系表设计:
通过设置“中间表”来关联两个“多”表。中间表中至少有两个外键字段,分别关联于两个“多”表(其他两个表)的主键。
在Django的models.py中需要完成三个模型:
方式一:自行创建第三张表
class Book(models.Model):
title = models.CharField(max_length=32, verbose_name="书名")
class Author(models.Model):
name = models.CharField(max_length=32, verbose_name="作者姓名")
# 自己创建第三张表,分别通过外键关联书和作者
class Author2Book(models.Model):
author = models.ForeignKey(to="Author")
book = models.ForeignKey(to="Book")
class Meta:
unique_together = ("author", "book")
方法二:通过ManyToManyField自动创建第三张表
class Book(models.Model):
title = models.CharField(max_length=32, verbose_name="书名")
# 通过ORM自带的ManyToManyField自动创建第三张表
class Author(models.Model):
name = models.CharField(max_length=32, verbose_name="作者姓名")
books = models.ManyToManyField(to="Book", related_name="authors")
方式三:设置ManyTomanyField并指定自行创建的第三张表
class Book(models.Model):
title = models.CharField(max_length=32, verbose_name="书名")
# 自己创建第三张表,并通过ManyToManyField指定关联
class Author(models.Model):
name = models.CharField(max_length=32, verbose_name="作者姓名")
books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book"))
# through_fields接受一个2元组('field1','field2'):
# 其中field1是定义ManyToManyField的模型外键的名(author),field2是关联目标模型(book)的外键名。
class Author2Book(models.Model):
author = models.ForeignKey(to="Author")
book = models.ForeignKey(to="Book")
class Meta:
unique_together = ("author", "book")
注意:
当我们需要在第三张关系表中存储额外的字段时,就要使用第三种方式。
但是当我们使用第三种方式创建多对多关联关系时,就无法使用set、add、remove、clear方法来管理多对多的关系了,需要通过第三张表的model来管理多对多关系。
class RelatedManager
"关联管理器"是在一对多或者多对多的关联上下文中使用的管理器。
它存在于下面两种情况:
外键关系的反向查询、多对多关联关系
简单来说就是当 点后面的对象 可能存在多个的时候就可以使用以下的方法。
方法:
create()
创建一个新的对象,保存对象,并将它添加到关联对象集之中,返回新创建的对象。
import datetime
models.Author.objects.first().book_set.create(title="番茄物语", publish_date=datetime.date.today())
add()
把指定的model对象添加到关联对象集中。
添加对象
author_objs = models.Author.objects.filter(id__lt=3)
models.Book.objects.first().authors.add(*author_objs)
添加id
models.Book.objects.first().authors.add(*[1, 2])
set()
更新model对象的关联对象。
book_obj = models.Book.objects.first()
book_obj.authors.set([2, 3])
remove()
# 从关联对象集中移除执行的model对象
book_obj = models.Book.objects.first()
book_obj.authors.remove(3)
clear()
# 从关联对象集中移除一切对象。
book_obj = models.Book.objects.first()
book_obj.authors.clear()
注意:
对于ForeignKey对象,clear()和remove()方法仅在null=True时存在。
举个例子:
ForeignKey字段没设置null=True时,没有clear()和remove()方法:
class Book(models.Model):
title = models.CharField(max_length=32)
publisher = models.ForeignKey(to=Publisher)
models.Publisher.objects.first().book_set.clear()
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: 'RelatedManager' object has no attribute 'clear'
当ForeignKey字段设置null=True时,
class Book(models.Model):
name = models.CharField(max_length=32)
publisher = models.ForeignKey(to=Class, null=True)
此时就有clear()和remove()方法:
models.Publisher.objects.first().book_set.clear()
注意:
对于所有类型的关联字段,add()、create()、remove()和clear(),set()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法。