字段关系
OneToOneField(一对一)
ForeignKey(一对多)
ManyToManyField(多对多)
models表设计基本原则:
- 一对一的表,两表的属性实际上完全可以合并成一个表,共用一个主键即可;
- 一对多的表,可以设中间关联表,也可以将关联表并入“多”这头;若设独立关联表,则可引入“多”这头的主键作为其主键,也可另立主键并将“一”和“多”两表的主键作为关联表的外键;
- 多对多的表,则必须设中间关联表,关联表设独立主键,并引入两个“多”头的表的主键作为关联表的外键。
- 能用1对1的,就不用1对多;能用1对多的,就不用多对多,往简单化方向靠;
- 能当属性处理的,尽量当属性,而不是当实体处理去另立新表,这样可使问题简化。
- 把意义相近联系紧密的属性放在一张表内,而不是拆在多张表中。
OneToOneField(一对一)
- model数据字段,最重要的就是设置外键
- 类似于继承,在设计模型时,可以将多个数据路中共有的字段集中起来,然后使用OneToOne,进行关联。
- 反向关联的对象只有一个,多数用于从一个模型扩展出另一个模型的情况。
一对一通过子对象访问关联的主对象:
<子对象>.<一对一键>
一对一通过主对象访问关联的子对象:
<主对象>.<小写子模型名>
注意:返回的是单个对象而不是集合
代码:
# 员工基本信息类和详细信息类是一对一的关系 # 员工基本信息类 class EmployeeBasicInfo(models.Model): # 姓名 name = models.CharField(max_length=20) # 关联属性,代表员工的详细信息 employee_detail = models.OneToOneField('EmployeeDetailInfo') # 定义在基本信息类或详细信息类中都可以。 # 员工详细信息类 class EmployeeDetailInfo(models.Model): # 联系地址 addr = models.CharField(max_length=256) # 关联属性,代表员工基本信息 # employee_basic = models.OneToOneField('EmployeeBasicInfo') # 定义在基本信息类或详细信息类中都可以。
ForeignKey(一对多)
多对一关系由外键实现,外键要定义在“多”的一方,如:
models.ForeignKey
(<主表>, ...)
如果要关联的主表在另一个app中,要显式的指出:
models.ForeignKey(’<app名称>.<主表>‘, ...)
可创建自己关联自己的外键——比如,在学科信息表中,学科分类可被多次引用并对应学科信息:
#创建学科分类表
class Type(models.Model):
id = models.AutoField(primary_key=True)
type_name = models.CharField(max_length=20)
#创建学科信息表
class Product(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=60)
weight = models.CharField(max_length=20)
size = models.CharField(max_length=20)
type = models.ForeignKey(Type,on_delete=models.CASCADE()) # 表示外键关联到Type表.
如果在子模型中存在多个外键指向同一个主模型,必须给他们加上不同的related_name,用于反向查询。
外键字段在数据库中的列名是<外键名>_id,用来储存主表对象的id,因此,在得到主表id的情况下可以不调用外键而直接筛选:
QuerySet = <外键表>.filter(<外键名>_id=<主表id>)#获得与“<主表id>=xxx的主对象”相关联的子对象
多对一的字段参数
on_delete=models.XXX当主对象被删除时,关联的子对象的操作(因为主键不能随意删除,外键可以直接删除)
models.CASCADE:同时删除关联的子对象,Django模拟SQL约束ON DELETE CASCADE的行为,并删除包含ForeignKey的对象
models.PROTECT:阻止CASCADE删除关联的子对象,并弹出ProtectedError异常
models.SET_NULL:将子对象的外键字段设为null(外键字段需设置null=True)
models.SET_DEFAULT:将子对象的外键字段设为默认值(外键字段需设置default=’xxx’)
models.DO_NOTHING:什么也不做。如果数据库后端强制执行参照完整性,则这将导致IntegrityError除非您手动将SQL约束添加到数据库字段。
models.SET():设置为一个传递给SET()的值或一个回调函数的返回值
注:on_delete是Django2.0之后新增的必选项。
related_name=’ ‘通过主对象反向引用子对象的通道名称,默认名称是<小写子模型名>_set。
如:class Car(models.Model):
factory = models.ForeignKey(Factory, on_delete=models.CASCADE, related_name='car_by_factory',)
此时Factory主表取出所有关联的Car对象:factory.car_by_factory.all()如果不想给外键设置反向关联名称,就用related_name=’+’或以+号结尾
related_query_name=’ ‘
主对象反向关联查询的名称,默认查询名称是<外键列>__<主表的某列>。
如:class Tag(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_query_name="tag", )
name = models.CharField(max_length=255)
此时用tag作为查询名称:
Article.objects.filter(tag__name="A")limit_choices_to={}
限制外键能关联的对象,用于Django的表单模块和admin后台,可以传入字典、Q对象、一个返回字典或Q对象的函数。
如:
staff_member = models.ForeignKey( User, on_delete=models.CASCADE, limit_choices_to={'is_staff': True},)
此时,表单模块的staff_member字段列表中只会出现is_staff=True的Users对象,对admin后台非常有用。
to_field=’ ‘
让外键关联到指定的字段上(默认关联到主键),该字段必须有unique=True属性。
ManyToManyField(多对多)
下章在写...