django-外键和表关系
Posted Jason_WangYing
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了django-外键和表关系相关的知识,希望对你有一定的参考价值。
首先说明下ForeignKey的选项
1.edit_inline:
如果不设为 False 的话,它对应的对象就可以在页面上内联编辑,就是说这个对象有自 己独立的
管理界面。如果设为 models.TABULAR 或者 models.STACKED 的话,这个内 联编辑对象分别显
示成一个表格或者一些字段的集合。
2.limit_choices_to:
可以限定对象的值的范围的一个参数和值的字典。结合Python的 datetime 模块的
函数可以根据日期来限定对象。例如,下面的代码:
limit_choices_to = {'pub_date__lte': datetime.now}
把可选对象限定到 pub_date 早于当前时间的对象中。
除字典外,这里也可以是一个可以执行更复杂的查询的 Q 对象
这个选项和 edit_inline 是不兼容的。
3.max_num_in_admin
于内联编辑对象,这个是要在管理界面里显示的相关对象的最多个数。所以,如果披萨最多 只会
有10种配料, max_num_in_admin=10 会保证用户最多输入10种配料。
记住,本项并不保证不会创建10种以上的配料,他只是控制管理界面,而不是在Python的API 层和
数据库层做什么限制。
4.min_num_in_admin
在管理界面中要显示的相关的对象的最少个数。通常,在创建的时候,显示的内联对象的个数 为
num_in_admin 个,在编辑的时候,在当前的基础上又会多显示 num_extra_on_change 个空对
象,但是显示的对象个数不会少于 min_num_in_admin 个。
5.num_extra_on_change
修改对象时要额外显示的对象数目。
6.num_in_admin
添加对象时要显示的内联对象的默认个数。
7.raw_id_admin
为要键入的整数显示一个文本框,而不是一个下拉列表。在关联对象有很多行时,这个比显示 一个
列表选择框更实用。
使用 edit_inline 时,本项无效。
8.related_name
关联对象反向引用描述符。
9.to_field
关联对象的用于关联的字段,Django默认使用关联对象的主键。
一对一Model
有外键即设置关联关系的一方为从表,从表查主表为正向查询,反之。这里护照为从表,人为主表。
class Passport(models.Model): # 护照(从表)
note = models.CharField(max_length=20)
person = models.OneToOneField(to="Person",on_delete=models.CASCADE,null=True) #关系属性
class Meta:
db_table="t_passport"
class Person(models.Model): # 人(主表)
name = models.CharField(max_length=20)
age = models.IntegerField()
class Meta:
db_table="t_person"
注:不需要手动设置 person字段唯一,自动会设置为唯一
一对一 一个人一本护照
# 1.只查 单方数据 (与单表数据查询一致)
# 只查人的信息
ps = Person.objects.filter(name='Tom').values() # 自己查自己
print(ps)
# 只查 护照的信息
p1 = Passport.objects.all().values()
print(p1)
ps = Person.objects.filter(passport='1').values()
print(ps)
# 2.通过一方查另一方数据 (先获取一方数据,再通过它查询另一方)
# 查询 名字为tom的护照信息
p1 = Person.objects.get(name='Tom')
print(p1.passport.note) #反向查询 基于对象 类名小写
# 查询护照为美国的人的信息
ps = Passport.objects.get(note='美国')
print(ps.per_id, ps.per.name,ps.per.age) #正向查询 基于对象 直接调用外键
# 3.通过一方 查另一方 (查询条件是对方)
# 查询名字为tom的护照信息
p1 = Passport.objects.filter(per__name='Tom').values() #正向查询 基于字段 外键__字段
print(p1)
# 查询护照为美国的人的信息
p1 = Person.objects.filter(passport__note='美国').values() #反向查询 基于字段 类小写__字段
print(p1)
print(Person.objects.filter(passport__note='美国')) # QuerySet集合对象
# 4.保留双方数据 ()
# 查询名字为Tom的人信息 和 护照的信息
p1 = Person.objects.filter(name='Tom').values('name','age','passport__note') #反向查询 基于字段 类小写__字段
print(p1)
p1 = Passport.objects.filter(per__name='Tom').values('note','per__name','per__age','per_id') #正向查询 基于字段 外键__字段
print(p1)
一对一查询总结:
正向查询时,基于对象,对象.直接调用外键;基于字段 外键__字段
反向查询时,基于对象,对象.类名小写;基于字段 类小写__字段
感觉从表和主表查起来差不多。
一对多Model
货物为从表,种类为主表
class Category(models.Model): #种类(主表)
title = models.CharField(max_length=20)
note = models.CharField(max_length=20)
class Meta:
db_table="t_category"
class Goods(models.Model): #货物(从表)
title = models.CharField(max_length=20,unique=True)
price = models.FloatField()
cate = models.ForeignKey(to=Category,on_delete=models.CASCADE) #关系属性 主表删除后,从表中使用主表中数据的也会跟随一起删除
class Meta:
db_table = "t_goods"
# 1对多关系 Category(1):没有关系属性 Goods(*):其中有关系属性cate
# 一对多 查询 category主表 goods从表
# 1.只查询一方数据
# 只查 主表
c1 = Category.objects.filter(name='服装').values()
print(c1)
g1 = Goods.objects.filter(price=5000).values()
print(g1)
# 2.通过一方查询另一方 (先查询到一方数据,再通过它查询另一方)
# 查询服装类别为男装的 商品名称
c1 = Category.objects.get(name='服装')
print(c1.goods_set) # 查询也是一个集合 #反向查询 基于对象 对象.表名_set
print(c1.goods_set.all()) # 查询也是一个集合
# 查询 商品沙发所属的类别
g1 = Goods.objects.get(title='沙发')
print(g1.cate.name, g1.cate.note) #正向查询 基于对象 对象.外键.字段
# 3.通过一方查询另一方(查询条件是另一方)
# 查询 床 商品的 类别信息
c1 = Category.objects.filter(goods__title='床').values() #反向查询 基于字段 表名__字段
print(c1)
# 查询分类为 家居 类别的 商品信息
g1 = Goods.objects.filter(cate__name='家居').values() #正向查询 基于字段 外键__字段
print(g1)
# 4.保留双方数据
# 查询商品名称为 电视 的分类信息 和 商品信息
c1 = Category.objects.filter(goods__title='电视').values('name','note','goods__title','goods__price') #反向查询 基于字段 表名__字段
print(c1)
# 查询商品价格大于5000的商品的分类信息
c1 = Category.objects.filter(goods__price__gt=5000) #反向查询 基于字段 表名__字段
print(c1)
print(set(c1))
#注意在进行联合查询时,可能会由重复数据出现,解决:
list(set(Category.objects.filter(goods__price__gt=200)))
一对多总结:
正向查询时,基于对象,对象.外键.字段;基于字段,外键__字段
反向查询时,基于对象,对象.表名_set;基于字段,表名__字段
多对多Model
class Student(models.Model): #学生(主表)
name = models.CharField(max_length=20)
age = models.IntegerField()
class Meta:
db_table="t_student"
class Course(models.Model): #课程(从表)
title = models.CharField(max_length=30)
expire = models.SmallIntegerField()
stu = models.ManyToManyField(to=Student) #关系属性
class Meta:
db_table="t_course"
# 多对多关系 Course:有对方关系属性students, Student:没有对方关系属性
# 1.只查询一方
# 查询学生 linda 学生信息
s1 = Student.objects.filter(name='Linda').values()
print(s1)
# 查询mysql课程信息
c1 = Course.objects.filter(title__icontains='MYSQL').values()
print(c1)
# 2.查询一方,通过它查询另一方
# 查询 学习mysql的学生信息
c1 = Course.objects.get(title='DJANGO')
print(c1.stu.all()) #正向查询 基于对象 对象.外键
# 查询 学生 linda 课程信息
s1 = Student.objects.get(name='Linda')
print(s1.course_set.all()) #反向查询 基于对象 对象.表名_set
print(s1.course_set.values())
# 3.通过一方 查询 另一方 (查询条件为对方)
# 查询 学生 linda 课程信息
c1 = Course.objects.filter(stu__name='Linda').values() #正向查询 基于字段 外键__字段
print(c1)
# 查询 学习mysql的学生信息
s1 = Student.objects.filter(course__title='PYTHON').values() #反向查询 基于字段 表名__字段
print(s1)
# 4.保留双方数据
# 查询学习django的学生信息 和 课程信息
s1 = Student.objects.filter(course__title='DJANGO').values('name','age','course__title','course__expire') #反向查询 基于字段 表名__字段
print(s1)
# 查询jack学习的课程信息 和 学生信息
c1 = Course.objects.filter(stu__name='Jack').values('title','expire','stu__age','stu__name') #正向查询 基于字段 外键__字段
print(c1)
#关联查询
Student.objects.filter(course__title__contains="h") #标题中含有"h"的课程中的学生 #反向查询 基于字段 表名__字段
Course.objects.filter(stu__name="zzz") #姓名为zzz的学生参加的课程 #正向查询 基于字段 外键__字段
Course.objects.filter(stu__age__gt=18) #年龄大于18的学生参加的课程 #正向查询 基于字段 外键__字段
坑:不能查具体某个字段
多对多总结:
正向查询时,基于对象,对象.外键;基于字段,外键__字段
反向查询时,基于对象,对象.表名_set;基于字段,表名__字段
最后3个总结写在一起比较:
一对一查询总结:
正向查询时,基于对象,对象.直接调用外键;基于字段 外键__字段
反向查询时,基于对象,对象.类名小写;基于字段 类小写__字段
一对多总结:
正向查询时,基于对象,对象.外键.字段;基于字段,外键__字段
反向查询时,基于对象,对象.表名_set;基于字段,表名__字段
多对多总结:
正向查询时,基于对象,对象.外键;基于字段,外键__字段
反向查询时,基于对象,对象.表名_set;基于字段,表名__字段
最后总结,
基于对象的情况下,正向查询时基本一致,直接调用外键就好;反向查询时一对多和多对多,需要对象.表名_set调用。
基于字段的情况下,正向查询时,外键__字段;反向查询时,表名__字段。一对一可能为类名小写__字段。
以上是关于django-外键和表关系的主要内容,如果未能解决你的问题,请参考以下文章