博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python之Django学习笔记(四)---数据模型(SQLITE3)以及相关操作
阅读量:4342 次
发布时间:2019-06-07

本文共 15747 字,大约阅读时间需要 52 分钟。

数据模型在djangoTestApp/models.py文件中定义表和表结构,之前已经定义了一个Student表,如下:

from django.db import modelsSEX_CHOICE = (    ('F','Female'),    ('M','male'))# Create your models here.class Student(models.Model):    No = models.CharField('学号',max_length = 10)    Name = models.CharField('姓名',max_length = 20)    Sex = models.CharField('性别',max_length = 1,choices = SEX_CHOICE,default = 'M')    Age = models.IntegerField('年龄')

字段类型主要有以下几种:

CharField:字符型

IntergerField:整型

DateField:日期型

DateTimeField:日期时间型

FloatField:浮点型

BooleanField:布尔型

BigIntergerField:大数据型

FileField:文件类型

...

当然类型也可以自定义

 

数据表创建好后在命令行中使用如下语句写入数据库:

python manage.py makemigrationspython manage.py migrate

命令行中输入如下命令可以进入数据库操作界面:

D:\PycharmProjects\untitled\MyTestProject\djangoTestPro>python manage.py shell >>> from djangoTestApp import models

 

 

一、增加操作

在django中增加有如下4种方式:

1、直接使用create增加

>>>models.Student.objects.create(No='19001',Name='watertaro',Sex='M',Age=30)

 

2、先创建一个对象再保存

>>>p = models.Student(No='19002',Name='Mark',Sex='F',Age=27)>>>p.save

 

3、先创建一个对象,给对象的参数赋值后再保存

>>> p = models.Student()>>> p.No='19005'>>> p.Name='WangWU'>>> p.Sex='M'>>> p.Age=35>>> p.save()

 

4、查看和增加,不存在则增加,存在则查询

>>> models.Student.objects.get_or_create(No='19006',Name='LiLiu',Sex='F',Age=21)(
, True)

返回一个元祖,第一个表示对象,第二个参数True表示新增,False表示查询

再次执行上述命令则返回的第二个参数为False(已经执行过一次,表示已经存在数据了)

 

 

二、查询操作

get()方法:

>>> models.Student.objects.get(No='19003')

这里只显示查到了数据,可以使用__dict__(这里是俩个下划线)来查看(返回的是一个字典)

>>> models.Student.objects.get(No='19002').__dict__{
'_state':
, 'id: 4, 'No': '19002', 'Name': 'Mark', 'Sex': 'F', 'Age': 27}>>> s = models.Student.objects.get(No='19002')>>> s.__dict__{
'_state':
, 'id: 4, 'No': '19002', 'Name': 'Mark', 'Sex': 'F', 'Age': 27}

也可以在数据模型的类(即Student类)中增加一个__str__的返回值:

def __str__(self):        return 'No:' + self.No + ';Name:' + self.Name + ';Sex:' + self.Sex + ';Age:' + str(self.Age)

使用exit()退出shell再重新进入,再次查询如下:

>>> models.Student.objects.get(No='19003')

get()方法只能查询到有且只有一条数据的对象,如果没有查询到或者查询结果不止一条会报错,后面会讲到可以查询N条数据方法(filter)

 

all()方法

可以查询表中所有数据,如下:

>>> models.Student.objects.all()
,
,
,
,
,
]>

 若只是查询前2条数据,可以使用类似列表中切片方法来查询(这里切片不支持负数

>>> models.Student.objects.all()[:2]
,
]>

如果只需要显示Name,可以按照如下操作:

>>> t = models.Student.objects.all()>>> item = models.Student.objects.all()>>> for i in item:...     print(i.Name)...watertaroMarkZhangSanLiSiWangWU

 

filter()方法:

filter可以查询出多条或者空数据,这也是查询中使用最多的方法,下面介绍使用方法

 1、精确查询(__exact)和不区分大小写的精确查询(__iexact)

>>> models.Student.objects.filter(No='190')#查询为空
>>> models.Student.objects.filter(No='19001')#查询到一条数据
]>>>> models.Student.objects.filter(Age=30)#查询到多条数据
,
]>

也可以使用No__exact(双下划线)来精确查询和直接查询的效果是一样的,如下:

>>> models.Student.objects.filter(No__exact='190')#查询为空
>>> models.Student.objects.filter(No__exact='19001')#查询到一条数据
]>>>> models.Student.objects.filter(Age__exact=30)#查询到多条数据
,
]>

 

之前Name中有watertaro,增加一个WaterTaro这个Name:

>>> models.Student.objects.create(No='19007',Name='WaterTaro',Sex='F',Age=29)

这时使用如下查询语句可以看到后一个查询语句不区分大小写,但是精确匹配的:

>>> models.Student.objects.filter(Name='WaterTaro')
]>>>> models.Student.objects.filter(Name__exact='WaterTaro')
]>>>> models.Student.objects.filter(Name__iexact='WaterTaro')
,
]>

3、包含某个字段的查询(__contains和__icontains)

>>> models.Student.objects.filter(Name__contains='watertaro')
,
]>>>> models.Student.objects.filter(Name__icontains='watertaro')
,
]>

老版本中__contains是区分大小写的,最新django不区分

4、正则表达式查询(__regex)和不分区大小写的正则表达式查询(__iregex)

我们增加一个Name为LuTao的同学:

>>> models.Student.objects.create(No='19008',Name='LuTao',Sex='F',Age=25)

此时查询以u结尾的名字

>>> models.Student.objects.filter(Name__regex='u$')
]>

只能查到LiLiu,其实包含u和U的名字还有LuTao和WangWU,如果使用下面的语句,则可以查到LiLiu和WangWU

>>> models.Student.objects.filter(Name__iregex='u$')
,
]>

5、大于(gt)、大于等于(gte)、小于(lt)、小于等于(lte) 

看下面查询的例子:

>>> models.Student.objects.filter(Age__gt=30)#查询Age大于30
]>>>> models.Student.objects.filter(Age__gte=30)#查询Age大于等于30
,
,
]>>>> models.Student.objects.filter(Age__lt=29)#查询Age小于29
]>>>> models.Student.objects.filter(Age__lte=29) #查询Age小于等于29
,
,
]>

6、以某字段开始(startswith)、以某字段结束(endswith)

>>> models.Student.objects.filter(Name__startswith='wa')#以wa开始的Name(不区分大小写)
,
,
]>>>> models.Student.objects.filter(Name__endswith='n')#以n结尾的Name(不区分大小写)
]>

7、与(&)、或(|)

>>> models.Student.objects.filter(Age=30) & models.Student.objects.filter(Sex='F')#查询Age=30并且Sex为F
]>>>> from django.db.models import Q>>> models.Student.objects.filter(Q(Age=30) & Q(Sex='F'))#等同于上面查询
]>>>> models.Student.objects.filter(Age=30) | models.Student.objects.filter(Age=35)#查询Age为30或者35
,
,
]>>>> models.Student.objects.filter(Q(Age=30)|Q(Age=35))#等同于上面查询
,
,
]>

8、查询集中的第一条数据(first())、查询集中的最后一条数据(last())

>>> models.Student.objects.all()#查询所有
,
,
,
,
,
]>>>> models.Student.objects.all().first()#获取第一条数据
>>> models.Student.objects.all().last()#获取最后一条数据

 

exclude()方法:

exclude是排除方法,即查询到的是排除给出的条件,比如我们要查询不带u的Name

>>> models.Student.objects.exclude(Name__contains='u')
,
,
,
,
]>

查询结果中确实少了带u的3个同学:LuTao,LiLiu,WangWU

方法之间也可以连起来用,比如查询带u或U的名字但Age不为21的同学:

>>> models.Student.objects.filter(Name__contains='u').exclude(Age=21)
,
]>

结果中少了Age=21的LiLiu同学

 

count()方法:

查询结果的条数

>>> models.Student.objects.all().count()8>>> models.Student.objects.exclude(Name__regex='u$').count()7>>> models.Student.objects.exclude(Name__iregex='u$').count()6

因为查询结果是一个QuerySet集,是可以迭代的,所以条数也可以使用下面方法,但不建议使用:

>>> len(models.Student.objects.all())8>>> len(models.Student.objects.exclude(Name__regex='u$'))7>>> len(models.Student.objects.exclude(Name__iregex='u$'))6

 

reverse()方法:

前面说了数据库查询结果切片不支持负索引,那如果要查询最后一条数据就要用到reverser()方法了:

>>> models.Student.objects.all().order_by('Age')#根据Age排序
,
,
,
,
,
]>>>> models.Student.objects.all().order_by('Age').reverse()#reverse()类似order_by('-Age')
,
,
,
,
,
]>>>> models.Student.objects.all().order_by('Age').reverse()[0]#查询最后一条数据
>>> models.Student.objects.all().order_by('Age').reverse()[:1]#查询最后一条数据
]>>>> models.Student.objects.all().order_by('Age').reverse()[:2]#查询最后俩条数据
,
]>>>> models.Student.objects.all().order_by('Age').reverse()[1]#查询倒数第二条数据

 

query方法:

在每个执行语句中加一个.query即可查询,如下所示:

>>> print(str(models.Student.objects.all().query))#查看SELECT "djangoTestApp_student"."id", "djangoTestApp_student"."No", "djangoTestApp_student"."Name", "djangoTestApp_student"."Sex", "djangoTestApp_student"."Age" FROM "djangoTestApp_student">>> print(str(models.Student.objects.filter(Q(Age=30)&Q(Sex='F')).query))#查看SELECT "djangoTestApp_student"."id", "djangoTestApp_student"."No", "djangoTestApp_student"."Name", "djangoTestApp_student"."Sex", "djangoTestApp_student"."Age" FROM "djangoTestApp_student" WHERE ("djangoTestApp_student"."Age" = 30 AND "djangoTestApp_student"."Sex" = F)

 

values方法和values_list方法:

values方法返回的是dict类型数据,values_list返回的是元祖型数据,如下所示

>>> models.Student.objects.values('No')
>>> models.Student.objects.values_list('No')
>>> models.Student.objects.values_list('No',flat=True)#使用flat直接显示单个字段,不需要元祖

 

defer()方法

defer是不去查询某字段,如查询Student表,但不查询Age这个字段的值

>>> models.Student.objects.all().defer('Age').query.__str__()'SELECT "djangoTestApp_student"."id", "djangoTestApp_student"."No", "djangoTestApp_student"."Name", "djangoTestApp_student"."Sex" FROM "djangoTestApp_student"'

可以查询类SQL语句中并没有查询Age这个字段

 

only()方法:

只查询某字段,如Student表中,只查询Name这个字段

>>> models.Student.objects.all().only('Name').query.__str__()'SELECT "djangoTestApp_student"."id", "djangoTestApp_student"."Name" FROM "djangoTestApp_student"'

 

 

三、更新操作:

 更新有俩种方法如下

>>> models.Student.objects.filter(Name__contains='u')
,
,
]>>>> models.Student.objects.filter(Name__contains='u').update(Age=100)3>>> models.Student.objects.filter(Name__contains='u')
,
,
]>

update之后返回的是更新的数据个数,这个适合多条数据的更新

 

>>> t = models.Student.objects.get(Name='WangWU')>>> t
>>> t.Sex='F'>>> t.Age=35>>> t
>>> t.save()>>> t

上面这种方式是查询出一条数据,然后对其对象进行修改,最后一定记得要保存

 

 

四、删除操作:

删除关键字delete(),如下使用

>>> models.Student.objects.filter(Name__iexact='lutao')
]>>>> models.Student.objects.filter(Name__iexact='lutao').delete()(1, {
'djangoTestApp.Student': 1})>>> models.Student.objects.filter(Name__iexact='lutao')

或者如下先查询,再删除

>>> s = models.Student.objects.filter(Name__iexact='liliu')>>> s
]>>>> s.delete()(1, {
'djangoTestApp.Student': 1})>>> s

 

 

 五、排序操作:

和oracle一样关键字为order_by()

>>> models.Student.objects.all().order_by('Name')
,
,
,
,
,
]>>>> models.Student.objects.all().order_by('-Name')
,
,
,
,
,
]>

字段前面加连接符(-)标识倒序查询

 

 

六、去重操作:

去重关键字distinct()

当前django版本在shell中使用|合并时已经进行了去重操作,所以这个关键字暂时用不着

>>> a = models.Student.objects.filter(Name__contains='u')>>> b = models.Student.objects.filter(Age=29)>>> c = models.Student.objects.filter(Sex='M')>>> a
]>>>> b
,
]>>>> c
,
,
]>>>> abc = a | b |c>>> abc
,
,
,
]>

如上a、b、c中是有重复的,但合并为abc之后并没有看到重复项

 

 

七、起别名

和SQL类型,我们也可以使用as给每个字段起别名

>>> t = models.Student.objects.all().extra(select={
'MyName':'Name'})#把字段Name起个名MyName>>> t
,
,
,
,
,
]>>>> t[0].Name'watertaro'>>> t[0].MyName#和Name一样'watertaro'>>> models.Student.objects.all().extra(select={ 'MyName':'Name'}).query.__str__()#查询类似SQL的语句'SELECT (Name) AS "MyName", "djangoTestApp_student"."id", "djangoTestApp_student"."No", "djangoTestApp_student"."Name", "djangoTestApp_student"."Sex", "djangoTestApp_student"."Age" FROM "djangoTestApp_student"'

 

 

八、聚合计算

在models.py中增加一张分数表Score,用于聚合计算

class Score(models.Model):    No = models.CharField('学号', max_length=10)    Name = models.CharField('姓名', max_length=20)    Course = models.CharField('学科',max_length = 10)    Score = models.IntegerField('成绩',default = 0)    def __str__(self):        return 'No:' + self.No + ';Name:' + self.Name + ';Course:' + self.Course + ';Score:' + str(self.Score)

在命令行中执行如下语句

D:\PycharmProjects\untitled\MyTestProject\djangoTestPro>python manage.py makemigrationsD:\PycharmProjects\untitled\MyTestProject\djangoTestPro>python manage.py migrate

进入python shell增加数据如下:

D:\PycharmProjects\untitled\MyTestProject\djangoTestPro>python manage.py shell>>> from djangoTestApp import models>>> models.Score.objects.create(No='19001',Name='watertaro',Course='Chinese',Score=56)
>>> models.Score.objects.create(No='19002',Name='Mark',Course='Chinese',Score=70)
>>> models.Score.objects.create(No='19003',Name='ZhangSan',Course='Chinese',Score=68)
>>> models.Score.objects.create(No='19004',Name='LiSi',Course='Chinese',Score=91)
>>> models.Score.objects.create(No='19005',Name='WangWU',Course='Chinese',Score=82)
>>> models.Score.objects.create(No='19007',Name='WaterTaro',Course='Chinese',Score=66)
>>> models.Score.objects.create(No='19001',Name='watertaro',Course='Math',Score=78)
>>> models.Score.objects.create(No='19002',Name='Mark',Course='Math',Score=81)
>>> models.Score.objects.create(No='19003',Name='ZhangSan',Course='Math',Score=66)
>>> models.Score.objects.create(No='19004',Name='LiSi',Course='Math',Score=80)
>>> models.Score.objects.create(No='19005',Name='WangWU',Course='Math',Score=55)
>>> models.Score.objects.create(No='19007',Name='WaterTaro',Course='Math',Score=78)
>>> models.Score.objects.create(No='19001',Name='watertaro',Course='English',Score=70)
>>> models.Score.objects.create(No='19002',Name='Mark',Course='English',Score=51)
>>> models.Score.objects.create(No='19003',Name='ZhangSan',Course='English',Score=59)
>>> models.Score.objects.create(No='19004',Name='LiSi',Course='English',Score=90)
>>> models.Score.objects.create(No='19005',Name='WangWU',Course='English',Score=73)
>>> models.Score.objects.create(No='19007',Name='WaterTaro',Course='English',Score=60)
>>> models.Score.objects.all()
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
]>

 

1、聚合计数:类似SQL中的group by字段,如下求各年龄的人数

>>> from django.db.models import Count >>> models.Student.objects.values('Age').annotate(cnt=Count('Age')).values('Age','cnt')#以Age为分组,查询每个Age有几个人

使用query可以看到具体释义

>>> models.Student.objects.values('Age').annotate(cnt=Count('Age')).values('Age','cnt').query.__str__()'SELECT "djangoTestApp_student"."Age", COUNT("djangoTestApp_student"."Age") AS "cnt" FROM "djangoTestApp_student" GROUP BY "djangoTestApp_student"."Age"'

这里的Count是对查询出的Age条数进行统计,不一定为Age。cnt即为

2、聚合求和:类似SQL中的sum字段,如下求所有同学的所有课程的总分

>>> from django.db.models import Sum #导入Sum>>> models.Score.objects.values('No','Name').annotate(sum_score=Sum('Score')).values('No','Name','sum_score')#查询同学的总分

结合前面的排序,以总分从高到低排序如下

>>> models.Score.objects.values('No','Name').annotate(sum_score=Sum('Score')).values('No','Name','sum_score').order_by('-sum_score')

3、聚合求平均数:类似SQL中的avg字段,如下求每门课程的平均分

>>> from django.db.models import Avg #导入Avg>>> models.Score.objects.values('Course').annotate(avg_course=Avg('Score')).values('Course','avg_course')
>>> models.Score.objects.values('Course').annotate(avg_course=Avg('Score')).values('Course','avg_course').query.__str__()'SELECT "djangoTestApp_score"."Course", AVG("djangoTestApp_score"."Score") AS "avg_course" FROM "djangoTestApp_score" GROUP BY "djangoTestApp_score"."Course"'

从上可以看到各门课程的平均值,查看执行的类SQL语句,意思都差不多,只是写法稍微不同

4、聚合求最小值:类似SQL中的min字段,如下求每门课程的最低分数

>>> from django.db.models import Min#导入Min>>> models.Score.objects.values('Course').annotate(min_course=Min('Score')).values('Course','min_course')

5、聚合求最大值:类似SQL中的max字段,如下求每门课程的最高分数

>>> from django.db.models import Max#导入Max>>> models.Score.objects.values('Course').annotate(min_course=Max('Score')).values('Course','min_course')

 

 

九、字段聚合显示

比如Student表中,如果想把姓名(Name)和学号 (No)合并显示为Name(No),比如No=19001显示为watertaro(19001),可以如下操作

1、在Student表类中增加如下代码

class Student(models.Model):    No = models.CharField('学号',max_length = 10)    Name = models.CharField('姓名',max_length = 20)    Sex = models.CharField('性别',max_length = 1,choices = SEX_CHOICE,default = 'M')    Age = models.IntegerField('年龄')    def name_no(self):        return self.Name + '(' + self.No + ')'    name_no.short_description = '姓名(学号)'    NameNo = property(name_no)

2、在admin.py中修改显示字段

class StudentAdmin(admin.ModelAdmin):    list_display = ('NameNo','Sex','Age',)

 

此时刷新界面就会显示如下样式:

 

 

 

完结!

 

转载于:https://www.cnblogs.com/watertaro/p/10579397.html

你可能感兴趣的文章
Java新建Web应用与配置Tomcat流程
查看>>
BZOJ1037 [ZJOI2008]生日聚会Party 【DP】
查看>>
J2EE项目开发中常用到的公共方法
查看>>
linux文件与目录管理(2)
查看>>
兰州商学院正式更名为兰州財经大学
查看>>
python第二十八天,(元类,异常处理,)
查看>>
eclipse下进行c开发,使用zeromq
查看>>
翰思博客
查看>>
阿里云CentOS7搭建SVN服务器
查看>>
(转)每天一个linux命令(15):tail 命令
查看>>
拿不起怎么会放得下呢
查看>>
Python3爬虫(八) 数据存储之TXT、JSON、CSV
查看>>
源码安装caffe2时遇到的问题解决办法
查看>>
Window 相关命令
查看>>
Redis学习-hash数据类型
查看>>
系统进程 zygote(三)—— app_process 的 main 函数
查看>>
【我的学习笔记】汇总
查看>>
漫谈可视化Prefuse(六)
查看>>
转:如何提高测试用例设计的测试覆盖率
查看>>
MFC常用类
查看>>