文章目录
一、数据库的基本概念
模型(数据库)
基本概念:Django模型是Django框架中用于定义数据结构的核心组件。每个模型对应数据库中的一张表,模型的属性对应表的字段。通过模型,开发者可以用Python代码操作数据库,无需直接编写SQL语句
定义方式:在Django应用的models.py文件中定义模型类,继承自django.db.models.Model。每个类属性代表一个数据库字段,字段类型由Django的字段类决定
| 常用字段类型 | 含义 |
|---|---|
| AutoField | 自动增长的IntegerField(不指定时Django会自动创建属性名为id的自动增长属性) |
| CharField | 字符串(max_length表示最大字符个数) |
| TextField | 大文本字段(一般超过4000个字符时使用) |
| IntegerField | 整数 |
| FloatField | 浮点数 |
| DecimalField | 十进制浮点数(参数max_digits表示总位数,参数decimal_places表示小数位数) |
| BooleanField | 布尔值(True、False) |
| NullBooleanField | 支持Null、True、False三种值 |
| DateField | 日期,参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间截,它总是使用当前日期,默认为False; 参数auto now add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为False: 参数auto now add和auto now是相互排斥的,组合将会发生错误 |
| TimeField | 时间,参数同DateField |
| DateTimeField | 日期时间,参数同DateField |
| FileField | 上传文件字段 |
| lmageField | 继承于FileField,对上传的内容进行校验,确保是有效的图片 |
| ForeignKey | 定义多对一关系 |
| ManyToManyField | 定义多对多关系 |
| OneToOneField | 定义一对一关系 |
| 选项 | 说明 |
|---|---|
| null | 是否为空 |
| unique | 唯一 |
| default | 设置默认值 |
| varbose_name | 主要是admin后台显示名字 |
外键 :在设置外键时,需要通过
on_delete选项指明主表除数据时,对于外键引用表数据如何处理
| on_delete 参数 | 含义 |
|---|---|
| on_delete=None | 删除关联表中的数据时,当前表与其关联的field的行为 |
| on_delete=models.CASCADE | 级联(删除主表数据时连通一起删除外键表中数据) |
| on_delete=models.DO_NOTHING | 删除关联数据,什么也不做 |
| on_delete=models.PROTECT | 保护(通过抛出ProtectedError异常,来阻止删除主表中被外键应用的数据) |
| on_delete=models.SET_NULL | 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空,一对一同理) |
| on_delete=models.SET_DEFAULT | 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值,一对一同理) |
| on_delete=models.SET | 删除关联数据(与之关联的值设置为指定值,设置:models.SET(值); 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)) |
二、数据库的基本开发步骤
模型开发步骤 :
- 定义模型类(子应用的
models.py)
python
from django.db import models
class BookInfo(models.Model):
name = models.CharField(max_length=10, unique=True, verbose_name='名字') # 唯一
# 发布日期
pub_data = models.DateField(null=True)
# 阅读量
readcount = models.IntegerField(default=0)
# 评论量
commentcount = models.IntegerField(default=0)
# 是否逻辑删除
is_delete = models.BooleanField(default=False)
class Meta:
# 改表名
db_table = 'bookinfo'
# 修改后台admin的显示信息的配置
verbose_name = 'admin'
def __str__(self):
return self.name
class PeopleInfo(models.Model):
name = models.CharField(max_length=10)
gender = models.BooleanField()
# 外键 表与表之间关联的时候,必须要写 on_delete 参数,否则会报异常
book = models.ForeignKey(BookInfo, on_delete=models.CASCADE)
- model编写完后,执行指令生成迁移文件:
python manage.py makemigrations(需 settings.py 提前关联配置,否则会失败)- 执行指令实现迁移:
python manage.py migrate(会在数据库中生成表)
执行完成,在主应用的 settings.py 中可以查看使用的是什么数据库(根据下面文件,根目录下会生成db.sqlite3数据库文件)
python
DATABASE = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
三、创建管理员账户管理数据库
自带登入功能
项目运行
python manage.py runserver之后,浏览页面http://127.0.0.1:8000/admin会自动跳到登入页面

此时查询auto_user数据库是没有数据的,需要使用指令创建一个后台管理用户,
python manage.py createsuperuser,运行指令后输入账号、邮箱、密码,执行指令后再次查看auto_user数据库中有一条数据,然后通过浏览
http://127.0.0.1:8000/admin页面,输入账号和密码可以登入,在这可以进行写数据相关操作如果在数据库中没有展示具体内容,可能要在对应的models.py中添加__str__相关内容
python
from django.db import models
class BookInfo(models.Model):
name = models.CharField(max_length=10)
def __str__(self):
return self.name
在子应用的admin.py中添加如下内容
python
from django.contrib import admin
from login.models import BookInfo
# Register your models here.
admin.site.register(BookInfo)
在子应用的apps.py类中可以添加变量verbose_name修改标题(verbose_name='后台相关'),修改后,settings.py中INSTALLED_APPS中要以login.apps.LoginConfig格式来,然后
http://127.0.0.1:8000/admin对应数据库的模块标题就会变为指定的

四、数据库切换与配置
在主应用的
__init__.py中输入如下内容
python
import pymysql
pymysql.install_as_MySQLdb()
修改主应用的settings.py修改这段代码进行配置
python
# 小型数据库:Sqlite
# 中型数据库:MySQL,Sqlserver
# 大型数据库:oracle,DB2
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 主机
'PORT': '3306', # 端口
'USER': 'root', # 用户名
'PASSWORD': 'mysql', # 密码
'NAME': 'book', # 指定数据库
}
}
然后运行:
python manage.py makemigrations现在数据库中还没有该数据库,再执行:
python manage.py migrate执行之后,数据库中就有对应数据表了
有了数据表之后,可以通过cmd链接数据库,对数据库进行操作,也可以在视图中对数据库操作
sql
from django.shortcuts import render
from django.http import HttpResponse
from book.models import BookInfo
# Create your views here.
def index(request):
# 到数据库中查询数据
books = BookInfo.objects.all()
# 组织数据
context ={'books': books}
# 传递给模板
# render(request, '', context)
return HttpResponse('index')
五、数据库操作
iPython(python manage.py shell)
终端执行
如果要手动执行sql指令,比如查询、插入数据,可以执行指令:
python manage.py shell然后执行下面代码
from book.models import BookInfo,BookInfo.objects.all()接着就会显示数据库中查询到的内容
代码中执行(如 views.py 视图中)
python
from book.models import BookInfo
def index(request):
# 新增数据
book = BookInfo(name='python', pub_data='2000-01-01')
book.save()
# ...
新增数据
sql
from book.models import BookInfo
# 新增数据 方式一
book = BookInfo(name='python', pub_data='2000-01-01')
book.save()
# 新增数据 方式二(直接入库)
# object模型的管理类 对模型的增删改查都找它
BookInfo.objects.create(name='java', pub_data='2001-01-02')
修改更新数据
sql
from book.models import BookInfo
# 方式一
book = BookInfo.objects.get(id=1) # 查询数据 相当于select * from bookinfo where id=1
book.readcount=20 # 更新数据
book.save() # 调用save保存
# 方式二
BookInfo.objects.filter(id=1).update(readcount = 100, commentcount = 200)
删除操作
sql
from book.models import BookInfo
# 方式一
book = BookInfo.objects.get(id=5) # 先获取数据
book.delete() # 调用删除方法
# 方式二
BookInfo.objects.filter(id=4).delete()
查询操作
sql
from book.models import BookInfo
# get得到某一个数据 不存在会抛出异常
try:
book = BookInfo.objects.get(id=1) # select * from bookinfo where id=1
print(book.name, book.readcount)
except Exception:
pass
# all 获取所有数据
book = BookInfo.objects.all()
# count 获取总个数
BookInfo.objects.count()
排序
sql
from book.models import BookInfo
BookInfo.objects.all().order_by('readcount') # 升序
BookInfo.objects.all().order_by('-readcount') # 降序
过滤查询(filter、get、exclude)
filter、get、exclude都是相当于where查询,类似于 select * from bookinfo where id=1
filter :筛选/过滤 返回多个结果
get : 返回1个结果
exclude :排除掉符合条似剩下的结果,相当于not
新式语法,如filter(字段名__运算符=值)
| 运算符 | 含义 |
|---|---|
| exact | 等于 (get(id=1)等效于get(id__exact=1)) |
| contains | 包含 |
| endswith | 以什么结尾 |
| isnull | 为空 |
| in | in判断 |
| gt | 大于 |
| gte | 大于等于 |
| lt | 小于 |
| lte | 小于等于 |
sql
from book.models import BookInfo
# 查询编号为1的图书
BookInfo.objects.get(id=1) # 返回单一对象 等效于 id__exact=1
BookInfo.objects.filter(id__exact=1) # 返回列表
# 查询书名含'笑'的图书
BookInfo.objects.filter(name__contains='笑')
# 查询书名以'部'结尾的图书
BookInfo.objects.filter(name__endswith='部')
# 查询书名为空的图书
BookInfo.objects.filter(name__isnull=True)
# 查询编号为1或3或5的图书
BookInfo.objects.filter(id__in=[1, 3, 5])
# 查询编号大于3的图书
BookInfo.objects.filter(id__gt=3)
# 查询数据id不为3的图书
BookInfo.objects.exclude(id=3)
# 查询1980年发表的图书
BookInfo.objects.filter(pub_data__year='1980')
# 查询1990年1月1日后发表的图书
BookInfo.objects.filter(pub_data__gt='1990-1-1')
# 多条件查询
BookInfo.objects.filter(id__gt=2).filter(readcount__gt=20)
字段间对比查询(F对象)
用于属性与属性之间的比较,F对象的语法形式
语法:
filter(字段名__运算符=F('字段名'))
sql
from book.models import BookInfo
from django.db.models import F
# 查询阅读量(readcount)大于等于评论量的图书(commentcount)
BookInfo.objects.filter(readcount__gt=F('commentcount'))
# 查询阅读量大于等于评论量两倍的图书
BookInfo.objects.filter(readcount__gt=F('commentcount')*2)
多条件查询(Q对象)
多条件查询,如:需要查询id大于2 并且阅读量大于20的书籍
语法:或:
Q()|Q();与:Q()&Q(); 非:~Q()
sql
from book.models import BookInfo
from django.db.models import Q
# 需要查询id大于2并且阅读量大于20的书籍
BookInfo.objects.filter(id__gt=2).filter(readcount__gt=20) # 方式一
BookInfo.objects.filter(id__gt=2, readcount__gt=20) # 方式二
# 方法三,使用Q对象
BookInfo.objects.filter(Q(id__gt=2)&Q(readcount__gt=20))
# 需要查询id大于2或者阅读量大于20的书籍,这时候需要用到Q对象
BookInfo.objects.filter(Q(id__gt=2)|Q(readcount__gt=20))
聚合函数(计算,累计)
聚合函数需要使用
aggregate方法语法格式:
aggregte(Xxx('字段'))
sql
from book.models import BookInfo
from django.db.models import Sum,Avg,Max,Min,Count
# 当前数据的阅读总量
BookInfo.objects.aggregate(Sum('readcount'))
联表查询(多表)
比如书籍中没有任何关于人物的字段,人物中有关专书籍的字段 book 外键,书籍和人物的关系是 l:n
语法形式 :通过书籍查询人物:
主表模型.关联模型类名小写_set.all()通过人物查询书籍:
从表模型(实例对象).外键
通过书籍查询人物(一对多):查询书籍为1的所有人物信息
sql
from book.models import BookInfo
# 查询书籍
book = BookInfo.objects.get(id=1)
# 根据书籍关联人物信息
book.peopleinfo_set.all()
通过人物查询书籍(多对一):查询人物为1的书籍信息
sql
from book.models import PeopleInfo
# 查询人物
person = PeopleInfo.objects.get(id=1)
# 根据人物查询书籍
person.book.name
联表查询过滤(多表)
语法形式 :
一对多
需要的是图书信息,已知条件是人物信息
filter(关联模型类名小写__字段__运算符=值)需要的是主表数据,已知条件是从表信息
filter(关联模型类名小写__字段__运算符=值)
多对一需要的是人物信息,已知条件是书籍信息
filter(外键__字段__运算符=值)需要是是从表数据,已知条件是主表信息
filter(外键__字段__运算符=值)
sql
from book.models import BookInfo
# 一对多
# 查询图书,要求图书人物为郭靖
BookInfo.objects.filter(peopleinfo__name__exact='郭靖')
BookInfo.objects.filter(peopleinfo__name='郭靖')
# 查询图书,要求图书中人物的表述包含'八'
BookInfo.objects.filter(peopleinfo__description__contains='八')
# 多对一
# 查询书名为"天龙八部"的所有人物
PeopleInfo.objects.filter(book__name='天龙八部')
PeopleInfo.objects.filter(book__name_exact='天龙八部')
# 查询困书阅读量大于30的所有人物
PeopleInfo.objects.filter(book__readcount__gt=30)
数据分页
python
from book.models import BookInfo
from django.core.paginator import Paginator
books = BookInfo.objects.all()
# 将数据分页
# object_list 结果集/列表
# per_page 每页多少记录
p = Paginator(books, 2)
# 获取第几页数据
books_page = p.page(1)
books_page[0]