orm读取和操作数据

 如下:定义一个 1对多 关系:

# 国家表
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)

创建方式:

方式1:

        obj= 类(name=”“)

        obj.save()
类实例化后, 然后用save,实际上就执行了sql,可以用 connection.queries 查看到

connction 是django 连接数据库时的一个东西

查询的时候要 导入才能用

from django.db import connection  补充:查看实际sql

 方式2:

        用objects的create方法,其中自动去save了

         类.objects.create(name='中国')

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表

        第二种:可以这么写:Student.objects.create(name='白月', grade=1, country_id=c1_id)

1.查询:

查询结果为多个的QuerySet列表形式

QuerySet对象的特性:

        支持链式调用

        惰性查询,仅仅在使用时才执行sql语句,如:len(), count(),  通过切片

对象列表

返回的是QuerySet列表的形式(仅数据对象)

Country.objects.all()

结果为:<QuerySet [<Country: Country object (1)>, <Country: Country object (2)>, <Country: Country object (3)>]>   

筛选数据:如果筛不出来就返回空的QuerySet列表  

Country.objects.filter(name="中国",id="1")         # 筛选方式1   且的关系 Country.objects.filter(name="中国").filter(id=1)   # 筛选方式2           

小技巧:

  如果id是 主键,可以写成 pk=* 对于查询级列表,

  可以像列表一样切片,  

  可以.first() .last() 最后一个 .count() 列表数量 .exists() 是否存在  .ordey_by排序详细看后面 

  可以进行 for 循环

含数据的列表 


返回的是QuerySet列表的形式(所有数据及所有字段)
   Country.objects.values()
   格式:
 <QuerySet [{'id': 1, 'name': '中国'}, {'id': 2, 'name': '美国'}, {'id': 3, 'name': '法国'}]>
   筛选展示如 Country.objects.values("name")
则结果为:<QuerySet [{'name': '中国'}, {'name': '美国'}, {'name': '法国'}]>
   筛选数据(类似where条件):Country.objects.values("name").filter(name="法国")
则结果为:<QuerySet [{'name': '法国'}]>


如下,可以这样把数据库的数据展示再页面上

补充:QuerySet API reference | Django documentation | Django

从官网中看到, Country.objects ,后面还可以加  value_list() 等等

[(字段数据1,字段数据2),(),()]

aggregate()  ,聚合运算

固定搭配:values  和  annotate  ,  分组父表的id,然后查询每个id的从表数据有多少个。

 用 value_list时,可以加flat=True的参数,但只能指定一个字段

 具体的对象

返回具体的对象:

类.objects.all()[0]     # 第一个

类.objects.all().first()   # 第一个

get方式根据字段查询:

Country.objects.get(id=1)

Country.objects.get(name="美国")        

 如果:查不到、或者查出来有多个,都会抛出异常, 所以最好使用有唯一约束的条件去查询下

查询的方式

QuerySet查询集列表的 过滤 查询类型

Country.objects.filter()   filter中的查询类型

 常用的:

        id__gt = 5   表示 大于5    注: id后面要默认带出关键字才能用(自定义的id好像才能用)
        id__lt = 5        小于5
        id__gte = 5  表示 大于等于5
        id__lte=5         小于等于5
        id__in=[1,2,5]

        name__exact="中国"         补充: name=“中国” 默认就是name__exact

       name__iexact="Abc"        全匹配,并忽略大小写


        name__contains='美'     包含
        name__icontains='x'        包含 忽略大小写


        name__startswith='中'    以中开头的
        name__icontains='x'

        name__endswith='国'        以国结束的
        name__iendswith='国'

补充===   filter()   的反义 用  exclude()  ,

        如   exclude(   name__contains='美' ) ,表示不包含 美   的数据

官网-model 中的 querySet 的  lookups:QuerySet API reference | Django documentation | Django

还有

        如:  __range =(开始时间,结束时间)

                __regex =r"^(An?|The) +"                --正则

 

外键字段用法补充:

如国家--人   一对多案例

学生表中有个country 字段,可以些country__国家表的字段,如

country__name

以上是两表查询,实际上还有多表查询(没试过)

外键表字段+ 查询条件,  如下:

list3=Student2.objects.filter(grade=1,country__name__icontains='国')
for i in list3:
    print(i.name)

多张表的查询举例:

关联方式总结:

 country__name    表示国家表的名字字段,  查学生用  Student2.objects.filter(条件)( 例3)

 students__grade  表示学生的grade字段。    查国家用 Country.objects.filter(条件)(  例4 )

 stu1.country           一学生属于哪个国家              (例1)

 c1.students            一个国家下的学生们             (例2)

------------------------1.已知一个学生,查其国家------------------------------------------------

查看某个学生,属于哪个国家,同上面的a
        s1 = Student.objects.get(name='白月') 
        s1.country.name

-------- 2.已知一个国家,查有哪些学生属于这个国家------------定义 related_name ,就能反向查询-

如:此列子是反向查询所有

例子4:是反向查询,并且过滤每个字段

方式1:
        cn = Country.objects.get(name='中国') 
        cn.student_set.all()    结果同Students.object.all()    的查询集列表
通过表Model名转化为小写 ,后面加上一个 _set, 来获取所有的反向外键关联对象

方式2:定义外键时:用related_name,指反向查询时用什么名字:        
       可以想象成。 给Country表增加了一个东西 叫 students。 某个国家.students  来使用

                cn.students .all()

class Student2(models.Model):
    name    = models.CharField(max_length=100)
    grade   = models.PositiveSmallIntegerField()
    country = models.ForeignKey(Country,
                                on_delete=models.PROTECT,
                                # 指定反向访问的名字
                                related_name='students'
                                )
 

------------------------  3.查子表-学生们,条件有学习的字段   、国家的字段。(关联查询)-------------

查看学生,一年级 且 国家为中国的(快捷写法,外键__外键表的字段名)         Student.objects.filter(grade=1,country__name='中国').values()

如果返回结果只需要 学生姓名外键表的国家名两个字段,可以这样指定values内容

Student.objects.filter(grade=1,country__name='中国') .values('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')

------------------------  4.查父表-国家表,条件为学生的字段---------(关联查询)----------------------------

Country.objects.filter(students__grade=1).values().distinct()

或:Country.objects.filter(students__name__contains="月")

students为上面讲的定义的related_name

注意:据说 .distinct()对MySQL数据库无效,我没有来得及验证。实测 SQLite,Postgresql有效。

逻辑关系

且关系:

一个filter中写多个条件,中间用逗号隔开,或者,链式调用,连续的filter   就是and关系

         如上的例子3就是且的关系。

  Student.objects.filter(grade=1,country__name='中国')

或者  Student.objects.filter(grade=1).filter(country__name='中国')

或关系:

from django.db.models import Q
qs = Student2.objects.filter(Q(name__contains="白") | Q(grade="1"))

查询集的排序:
Country.objects.all().order_by("name")  # 默认升序

# 降序的写法

        Country.objects.all().order_by("-name")        

# 多个字段排序的时候

        Student2.objects.all().order_by("-grade","name")

更新

更新一条数据,  直接改,然后save()一下

c1.name="新中国"

c1.save()

或者指定:要更新哪些字段   c1.save(update_fields=["name"])

批量更新多条数据、使用update方法 无需调用svae

Student2.objects.filter(name__contains="白").update(grade=4)

删除

使用delete()方法

c1.delete()

删除多条数据,也是用delete()方法

qurrset查询.delete()

如  Student2.objects.filter(name__contains="白").delete()

        #测试后,补上数据。

       c1 = Country.objects.get(name="中国")

       Student2.objects.create(name='白月', grade=1, country=c1)

项目举例:

相关知识点:

见:1. 常见的类视图_A~taoker的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值