Django 模型(model)与数据库

初步使用模型

Django 模型是与数据库相关的,与数据库相关的代码一般写在 models.py 中,Django 支持 Sqlite3、MySQL、PostgreSQL 等数据库,只需要在 settings.py 中配置即可,不用更改 models.py 中的代码,丰富的 API 极大的方便了使用。

我们继续沿用之前创建的 learn 这个 app 进行实验。修改 learn 中的 models.py 如下所示:

1
2
3
4
5
from django.db import models

class Person(models.Model):
name = models.CharField(max_length=30)
age = models.IntegerField()

这段代码中,我们新建了一个 Person 类,继承自 models.Model,一个人有年龄和姓名。这里用到了两种 Field,更多的可以查看本教程最后的链接处。

然后来执行同步数据库操作(我们使用默认的 sqlite3数据库,无需任何其他配置):

1
2
$ python3 manage.py makemigrations
$ python3 manage.py migrate

从反馈的 log 中可以看到,Django 生成了我们新建的 Person 这个表。Django 还为我们提供了丰富的 API,下面演示如何来使用它:

1
2
3
4
$ python3 manage.py shell
>>> from learn.models import Person
>>> Person.objects.create(name="Gua", age=22)
<Person: Person object>

我们新建了一个用户 Gua,那么如何从数据库中查询到它呢?

1
2
>>> Person.objects.get(name="Gua")
<Person: Person object>

我们用了一个 .objects.get() 方法查询出来符合条件的对象,但是查询结果中显示 <Person: Person object>,这里并没有显示出与 Gua 相关的信息,如果用户多了就无法知道查询出来是那一条数据。查询结果是否正确,我们重新修改一下 learn/models.py。

备注:name 和 age 等字段中不能有 __(双下划线,因为在Django QuerySet API中有特殊含义(用于关系,包含,不区分大小写,以什么开头或结尾,日期的大于小于,正则等)。也不能有Python中的关键字,name 是合法的,studentname 也合法,但是student_name不合法,try, class, continue 也不合法,因为它是Python的关键字( import keyword; print(keyword.kwlist) 可以打出所有的关键字)。

1
2
3
4
5
6
7
8
9
from django.db import models


class Person(models.Model):
name = models.CharField(max_length=30)
age = models.IntegerField()

def __str__(self):
return self.name

数据库增与取操作的多种方法

增操作

新建一个对象的写法有以下几种:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1
Person.objects.create(name = name, age = age)

# 2
p = Person(name = name, age = age)
p.save()

# 3
p = Person(name = name)
p.age = age
p.save()

# 4
Person.objects.get_or_create(name = name, age = age)

第四种方法是防止重复的很好方法,但是速度相对较慢,返回一个元祖,第一个为 Person 对象,第二个为 True 或 False 布尔量。新建时返回的是 True,已经存在时返回 False。

查操作

查找一个对象有更多的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 1
Person.objects.all()

# 2. 切片操作,获取10个人,不支持负索引,切片可以节约内存
Person.objects.all()[:10]

# 3
Person.objects.get(name = name)

# 4. get是用来获取一个对象的,如果需要获取满足条件的一些人,就要用到 filter
Person.objects.filter(name = "abc")

# 5. 名称为 abc 但是不区分大小写,可以找到 ABC, Abc, aBC,这些都符合条件
Person.objects.filter(name__iexact = "abc")

# 6. 名称中包含 "abc"的人
Person.objects.filter(name__contains = "abc")

# 7. 名称中包含 "abc",且abc不区分大小写
Person.objects.filter(name__icontains = "abc")

# 8. 正则表达式查询
Person.objects.filter(name__regex = "^abc")

# 9. 正则表达式不区分大小写
Person.objects.filter(name__iregex = "^abc")

# 10. 排除包含 WZ 的Person对象
Person.objects.exclude(name__contains = "WZ")

# 11. 找出名称含有abc, 但是排除年龄是23岁的
Person.objects.filter(name__contains="abc").exclude(age = 23)

有关模型的操作以及 Fields 的更多内容可以查看下列资料:

  • Django models 官方教程
  • Fields相关官方文档