python ORM关联表

python ORM关联表

定义两张表

# 国家表
class Country(models.Model):
    name = models.CharField(max_length=100)
    
# 学生表, country 字段是国家表的外键,形成一对多的关系
class Student(models.Model):
    name    = models.CharField(max_length=100)
    grade   = models.PositiveSmallIntegerField()
    country = models.ForeignKey(Country,                              on_delete=models.PROTECT)

然后,执行使定义生效到数据库中。

python manage.py makemigrations common
python manage.py migrate

然后,命令行中执行 python manage.py shell ,直接启动Django命令行,输入代码。

先输入如下代码,创建一些数据

from common.models import *
c1 = Country.objects.create(name='中国')
c2 = Country.objects.create(name='美国')
c3 = Country.objects.create(name='法国')
Student.objects.create(name='张三', grade=1, country=c1)
Student.objects.create(name='李四', grade=2, country=c1)
Student.objects.create(name='王五', grade=1, country=c1)
Student.objects.create(name='赵六', grade=2, country=c1)
Student.objects.create(name='Mike', grade=1, country=c2)
Student.objects.create(name='Gus',  grade=1, country=c2)
Student.objects.create(name='White', grade=2, country=c2)
Student.objects.create(name='Napolen', grade=2, country=c3)
由学生查国家
访问所有一年级的学生
Student.objects.filter(grade=1).values()
获取一年级所有的学生姓名
Student.objects.filter(grade=1).values('name')

根据对象访问外键表

访问某一个学生所在的国家
s1.Student.objects.get(name='张三')
s1.country.name
查找一年级的中国学生(注意:country__name两个横线)
Student.objects.filter(grade=1,country__name='中国').values()
如果需要学生姓名和国家2个字段
Student.objects.filter(grade=1,country__name='中国')\
     .values('name','country__name')
输出为:<QuerySet [{'name': '王五', 'country__name': '中国'}, {'name': '张三', 'country__name': '中国'}]>
也可以对获取的字段进行重命名,引入from django.db.models import F
# annotate 可以将表字段进行别名处理
Student.objects.annotate(
    countryname=F('country__name'),
    studentname=F('name')
    )\
    .filter(grade=1,countryname='中国').values('studentname','countryname')
由国家查学生,反向访问

通过 表Model名转化为小写 ,后面加上一个 _set 来获取所有的反向外键关联对象

获取所有中国的学生
cn = Country.objects.get(name='中国')
cn.student_set.all()

在定义Model的时候,外键字段使用 related_name 参数,像这样

# 国家表
class Country(models.Model):
    name = models.CharField(max_length=100)

# country 字段是国家表的外键,形成一对多的关系
class Student(models.Model):
    name    = models.CharField(max_length=100)
    grade   = models.PositiveSmallIntegerField()
    country = models.ForeignKey(Country,
                on_delete = models.PROTECT,
                # 指定反向访问的名字
                related_name='students')

就可以使用更直观的属性名,像这样

cn = Country.objects.get(name='中国')
cn.students.all()
反向过滤
Country.objects.filter(students__grade=1).values()
或者
Country.objects.filter(student__grade=1).values()

但是,我们发现,这种方式,会有重复的记录产生,如下

<QuerySet [{'id': 1, 'name': '中国'}, {'id': 1, 'name': '中国'}, {'id': 2, 'name': '美国'}, {'id': 2, 'name': '美国'}]>

可以使用 .distinct() 去重

Country.objects.filter(students__grade=1).values().distinct()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值