本篇笔记目录索引如下:

  1. model 准备

1、model 准备

在上一篇笔记中,我们新建了一个 application,增加了几个model 同步到了数据库,这次我们新建一个名为 blog 的application,同步数据结构。

大概分为以下几步:

  • python3 manage.py startapp blog
  • 将 'blog.apps.BlogConfig’, 写入 settings.py INSTALLED_APPS
  • 更新 blog/models.py
  • python3 manage.py makemigrations blog
  • python3 manage.py migrate blog

具体执行 migrate 的操作步骤,可以参见上一篇笔记。

blog/models.py 的具体内容如下:

# blog/models.py
from django.db import models class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField() def __str__(self):
return self.name class Author(models.Model):
name = models.CharField(max_length=200)
email = models.EmailField() def __str__(self):
return self.name class Entry(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
mod_date = models.DateField()
authors = models.ManyToManyField(Author)
number_of_comments = models.IntegerField()
number_of_pingbacks = models.IntegerField()
rating = models.IntegerField() def __str__(self):
return self.headline

2、增

有以下几种方法(以下操作皆在 python3 manage.py shell 环境中进行):

实例化,然后save() 保存

from blog.models import Blog
b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
b.save()

当执行 save() 操作之后,数据就会创建到数据库,因为主键 id 为自动增长的,所以id会自动赋值。

当然也可以先实例化一个空的 Blog,然后再赋值:

from blog.models import Blog
b = Blog()
b.name = 'hunter'
b.tagline = 'tag lines'
b.save()

save 之后,如果需要修改 name 的值,可以直接进行修改:

b.name = ‘python’
b.save()

使用 create() 方法创建

from blog.models import Blog
b = Blog.objects.create(name='hunter', tagline='tagline')

调用 create() 方法,会返回这条数据保存后的对象。

批量创建

如果要批量创建数据,用上面的方法大概的就是在一个循环里,挨个去实例化一个 Blog,然后执行 save() 操作。

但Django 提供了一个 bulk_create() 的方法,可以提高这个效率,使用示例如下:

from blog.models import Blog

blog_1 = Blog(name='hunter1', tagline='tagline1')
blog_2 = Blog(name='hunter2', tagline='tagline2')
blog_obj_list = [blog_1, blog_2] Blog.objects.bulk(blog_obj_list)

3、查

查询的语法有查询之后返回 QuerySet 的查询,比如 filter(),exclude()

也有 返回单个 object 的查询,比如 get()

对于 QuerySet,这个我们可以简单理解为是多个 object 实例形成的列表,但是这个列表是Django的一种特有的形式,具有能进行其他条件筛选的功能。

接下来简单介绍一下查询的功能:

filter(),过滤筛选,返回的是符合条件的数据

比如我们要搜索 Entry 表里,name 的值为 hunter 的数据,使用如下:

Entry.objects.filter(name='hunter')

exclude(),排除筛选,返回的是不符合条件的数据

比如我们要搜索 Entry 表里,name 的值不为 hunter 的数据:

Entry.objects.exclude(name='hunter')

链式查询:

Django 支持 链式查询,可以多个 filter 或者 exclude 条件累加,取的是 AND 的逻辑:

Entry.objects.filter(name='hunter').exclude(name='paul').filter(id=1)

懒加载:

Django 的查询有一个机制叫做懒加载,意思是只有当你真正需要去取数据的时候

系统才会去数据库获取数据,官方例子如下:

>>> q = Entry.objects.filter(headline__startswith="What")
>>> q = q.filter(pub_date__lte=datetime.date.today())
>>> q = q.exclude(body_text__icontains="food")
>>> print(q)

上述语句虽然看起来查询了三次数据库,但实际上只有最后 print(q) 的时候才去访问了数据库。

get()

前面讲的 filter 和 exclude 返回的都是 QuerySet,简单来说就是多个 object 形成的列表,而 get() 操作返回的直接是一条符合条件的 object。

比如:

blog = Blog.objects.get(id=1)

注意: get() 方法需要慎用,因为查询的条件在数据库里,有多条或者一条都没有的时候系统会报错。

get() 的查询一般仅用在我们能够确定 在数据库里有且仅有一条数据情况下。

对QuerySe进行切片

用 filter 对数据进行操作的时候,如果需要对数据的返回数量进行限制,需要用到 python 里的切片。

PS:数量的返回限制对应于 mysql 里的 limit 用法。

比如:

blog_list = Blog.objects.all()[1:5]

但是和 python 里的切片不一样的时候,Django 的查询不支持 负数查询,比如下面的操作是不被允许的:

Blog.objects.all()[-1]  # error
Blog.objects.all()[-1: 3] # error

字段条件查找:

在我们使用 mysql 的时候 where 后面会跟一些查询的限制条件,在Django 里用 双下划线来实现

比如 id 的值大于 5

Model.objects.filter(id__gt=5)

大于:gt

大于等于:gte

小于:lt

小于等于:lte

包含:in

是否为 null :isnull

精确查找:

精确查找使用 exact,一般查询的时候 后面不加上面的字段条件,都属于精确查找,不过默认是将 exact 字段省略。

比如,下面两条代码是一致的:

Blog.objects.get(id__exact=14)
Blog.objects.get(id=14)

查询外键关联数据

比如 Entry 这个 model 的外键是 Blog,我们想通过 查找 Blog 的 name 字段为 Hunter 的Entry 数据:

Entry.objects.filter(blog__name='Hunter')

如果你想反向搜索也是可以的,将 model 名称小写即可:

Blog.objects.filter(entry__headline='abc')

计算查找

在Django 中引用字段来进行比较,比如我们想实现如下功能:

select * from blog_entry where number_of_comments > number_of_pingbacks;

可以使用Django 中的 F,它的作用是 取值,取出其中的字段值,那么上述例子可以用 Django来实现可以是:

from django.db.models import F
Entry.objects.filter(number_of_comments__gt=F(“number_of_pinbbacks"))

还可以在使用中对 F() 进行一系列的操作:

Entry.objects.filter(number_of_comments__gt=F('number_of_pingbacks') * 2)
Entry.objects.filter(rating__lt=F('number_of_comments') + F('number_of_pingbacks'))

pk 使用方法

pk 意思是 primary key ,主键,可以直接使用 pk 来搜索,但在项目中一般是使用 id 作为主键,所以一般是等价于id的用法:

Blog.objects.filter(pk__gt=11)

Q 查询:

我们知道可以使用 filter 来进行 链式查询,那个逻辑是一个且的逻辑,那么 或 的逻辑应该如何处理呢

我们可以使用Q() 来实现

我们可以使用 Q() 来将一个个的条件 串起来,比如,我们想筛选 Blog 中 id= 3 或者 id = 4 的数据可以使用如下:

Blog.objects.filter(Q(id=3) | Q(id=4))

也可以实现 且 的功能Q() & Q()

取反:~Q()

4、删

如果要删除 objects,有两种方法,一种先获取 object,然后 delete()

blog = Blog.objects.get(id=1)
blog.delete()

或者通过 filter 来 批量删除:

Blog.objects.filter(id__gte=10).delete()

注意:如果有外键关联了 Blog,且 on_delete关系设置为 models.CASCADE,

那么删除相应的 Blog 的时候,对应的 关联的 Entry 数据也会被删除

5、改

批量更新:

Blog.objects.filter(id__gte=200).update(name='hunter')

单个更新:

blog = Blog.objects.get(id=1)
blog.name = ‘hunter’
blog.save()

以上就是我们这一篇笔记的全部内容,下一篇笔记将详细介绍Django model里的 各个字段类型以及字段属性值。

本文首发于本人微信公众号:Django笔记。

原文链接:Django笔记三之使用model对数据库进行增删改查

如果想获取更多相关文章,可扫码关注阅读:

最新文章

  1. 被误解的MVC和被神化的MVVM(转)
  2. JFreechart在linux下不显示及中文乱码问题
  3. Elasticsearch-2.3.x填坑之路
  4. Git最佳实践
  5. [moka同学代码]PHP初级知识:上传文件源码
  6. Java语言基础(三) Java注释
  7. 链接分析算法之:SALSA算法
  8. java_eclipse_svn 与服务器同步时 ,忽略某类型文件和文件夹
  9. Path.OS 模块的使用方法(转自DK的博客)
  10. 2017java预备作业2
  11. [补档][Hnoi2013]游走
  12. Spring cloud zuul跨域(二)
  13. Spring AOP实现 Bean字段合法性校验
  14. PDF 补丁丁 0.6.0.3355 版发布(修复阅读模式、书签缩放的问题)
  15. Java Web 域名
  16. CodeForces - 348D Turtles(LGV)
  17. redis实现消息队列&发布/订阅模式使用
  18. vmware workstation 下安装ubuntu
  19. 读jQuery源码释疑笔记3
  20. PHP 字符串包含判断

热门文章

  1. flutter TextField 使用prefixIcon图标和文字间距问题
  2. bzoj 3309
  3. JDK1.8下载、安装和环境配置教程——
  4. Sky Full of Stars
  5. 使用dumpbin查看dll文件中的api
  6. homework1(1)
  7. ubuntu | virtualbox报错:不能为虚拟电脑打开一个新任务
  8. tex基础
  9. 用python提取txt文件中的特定信息并写入Excel
  10. 网易面经-hashmap是否能存null(debug源码)