zoukankan      html  css  js  c++  java
  • 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()
  • 相关阅读:
    Randomization Tests
    关于Spring中的<context:annotationconfig/>配置
    PUT method support
    在对话框picture control中利用opengl进行绘图
    【学习笔记】《卓有成效的管理者》 第三章 我能贡献什么
    程序员的黄金时代
    nginx webdav配置
    iphone4s 如何强制关机
    并查集
    实战虚拟化存储设计之三MultiPathing
  • 原文地址:https://www.cnblogs.com/cupid10/p/15617609.html
Copyright © 2011-2022 走看看