一、简介
ORM对象关系映射,它允许你使用类和对象对数据库进行操作,从而避免通过SQL语句操作数据库
模型层: 负责和数据库之间进行通信
模型是一个Python类,它是由django.db.models.Model派生出的子类
一个模型类代表数据库中的一张表
模型类中每一个类属性都代表数据库中的一个字段
模型是数据交互的接口,是表示和操作数据库的方法和方式
二、基本配置
1.配置settings.py
shell
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mydatabase',
'USER': 'admin',
'PASSWORD': 'abc123,',
'HOST': '192.168.1.23',
'PORT': '3306',
}
}
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
常用配置
1.BASE_DIR:项目的绝对路径
2.DEBUG: 启动模式
True: 调试模式
检测代码改动后,立刻重启服务
Fasle: 正式启动模式 / 上线模式3.ALLOWED_HOSTS: 允许访问本机的客户端主机,'*' 表示允许所有主机
4.DATABASES: 连接的数据库
5.LANGUAGE_CODE: 显示语言
zh-Hans 表示用中文显示
2.安装mysqlclient
因为我们使用mysql作为后端,所以要安装mysqlclient库
shell
pip install mysqlclient
3.创建应用
创建app1应用。发现在应用目录下多了app1目录
python manage.py startapp app1
4.注册应用
在setting.py中注册app1应用
python
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app1' #在这里加入我们刚才创建的app1应用
]
5.创建对应的数据库表
c
create database mydatabase default character set utf8mb4;
grant all on mydatabase.* to 'admin'@'%' identified by 'abc123,';
grant all on mydatabase.* to 'admin'@'localhost' identified by 'abc123,';
grant all on mydatabase.* to 'admin'@'127.0.0.1' identified by 'abc123,'
flush privileges;
修改该数据库字符集
alter database mydatabase character set utf8mb4 collate utf8mb4_unicode_ci;
迁移数据库,也就是使用python语法创建默认的库
python
python manage.py migrate
在库中查看,已经生成默认的数据库
mysql
mysql> use mydatabase
mysql> show tables;
+----------------------------+
| Tables_in_mydatabase |
+----------------------------+
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+----------------------------+
10 rows in set (0.00 sec)
6.启动django测试
shell
python manage.py runserver
三、ORM(模型)
1.创建模型类流程
在"应用(app1)"下的models.py中编写模型类
c
[root@node5 music]# vim models.py
#文件中自动导入了models包,因为这是一个包,其实就是执行了__init__.py文件。在此文件中又导入了base.py中的Model类
from django.db import models
2.语法:
模型类名也就是表名
c
class 模型类名(models.Model):
字段名1 = models.字段类型(字段选项)
字段名2 = models.字段类型(字段选项)
3.实例
3.1 创建model类
编辑app1应用下的models.py文件
shell
class student(models.Model):
class Meta:
db_table = 'my_table1'
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=20)
age = models.IntegerField()
shell
解释:
class student是模型类 继承models.Model类
Meta: 是自定义生成的表名,如果不定义,表名就是"应用名" + "模型类"组合而成的表名
id,name,age 分别是表中的字段
3.3 开始创建表
这个过程就是将类转换成sql的过程。django中这个过程叫做迁移
python
python manage.py makemigrations
python manage.py migrate
3.4 验证
mysql
mysql> use mydatabase
mysql> desc my_table1;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(20) | NO | | NULL | |
| age | int(11) | NO | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
四、插入数据
1.方法1:
在app1应用的models.py文件中,直接写入以下语句进行插入数据
c
student.objects.create(id=1,name='zhangsan',age=20)
然后命令行执行
python manage.py migrate
查看数据,已经插入成功
mysql
mysql> select * from my_table1;
+----+----------+-----+
| id | name | age |
+----+----------+-----+
| 1 | zhangsan | 20 |
+----+----------+-----+
2.方法2
在视图函数中插入数据。
2.1 设置总路由
编辑项目目录下的urls.py文件
python
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('app1/',include('app1.urls')),
]
2.2 设置分路由
在app1应用下新建urls.py文件。内容如下
python
from django.urls import path
from .views import *
urlpatterns = [
path('', fun_app1),
]
2.3 设置视图函数文件
python
# 导入model类中的student类
from .models import student
from django.http import HttpResponse
def fun_app1(request):
# 实例化student类
s1 = student(id=3,name="lisi",age=22)
# 写入数据,保存到数据库中
s1.save()
return HttpResponse("写入数据库成功!")
五、单表查询数据
1.创建数据库表
我们在数据库中直接创建一个表,用于测试。这里不通过django自带迁移的功能的创建了。
mysql
mysql> use mydatabase
mysql> create table my_students1(id int primary key auto_increment,name char(32),age int);
mysql> insert into my_students1 (name,age) values('zhangsan',20),('lisi',20),('wangwu',21),('xiaohong',22),('xiaoming',23);
mysql> select * from my_students1;
+----+----------+------+
| id | name | age |
+----+----------+------+
| 1 | zhangsan | 20 |
| 2 | lisi | 20 |
| 3 | wangwu | 21 |
| 4 | xiaohong | 22 |
| 5 | xiaoming | 23 |
+----+----------+------+
5 rows in set (0.00 sec)
2.创建模型类
在应用下(app1)的models.py中创建模型类,与刚才在数据库中创建的表建立对应关系.
python
class students1(models.Model):
class Meta:
db_table = 'my_students1' #这里的表名称一定要和数据库中表名保持一致
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField()
3.查询集合all()
编辑app1下的视图函数文件
c
from .models import *
from django.http import HttpResponse
def fun_app1(request):
# students1.objects.all返回的是一个django封装的queryset集合。简单理解为一个集合就可以了。
# 集合中就是每行的记录,也是"模型类的实例对象"。这样遍历就是遍历每个实例对象。这样就可以打印每条数据了
list = students1.objects.all()
for i in list:
print(i.id,i.name,i.age)
return HttpResponse("查询成功")
访问视图url路径,日志输出查询数据如下:
python
[11/Feb/2024 16:12:57] "GET /app1/ HTTP/1.1" 200 12
1 zhangsan 20
2 lisi 20
3 wangwu 21
4 xiaohong 22
5 xiaoming 23
4.集合过滤filter()
filter的返回结果也是一个queryset集合
python
from .models import *
from django.http import HttpResponse
def fun_app1(request):
list = students1.objects.filter(age=20)
for i in list:
print(i.id,i.name,i.age)
return HttpResponse("查询成功")
访问视图url路径,日志输出查询数据如下:
python
1 zhangsan 20
2 lisi 20
[11/Feb/2024 16:18:05] "GET /app1/ HTTP/1.1" 200 12
4.1 大于查询__gt
shell
list = students1.objects.filter(age__gt=20)
for i in list:
print(i.id,i.name,i.age)
4.2 小于查询__lt
shell
list = students1.objects.filter(age__lt=23)
for i in list:
print(i.id,i.name,i.age)
4.3 模糊查询__contains
查询语法:字段名__contains="查询内容"
shell
list = students1.objects.filter(name__contains="xiao")
for i in list:
print(i.id,i.name,i.age)
5.get()
get函数的结果必须是一个结果,要是两个结果都不可以用这个。get的返回结果是一个模型类实例对象。不是queryset集合
python
list = students1.objects.get(id=1)
print(list.id,list.name,list.age)
6.取反exclude()
python
list = students1.objects.exclude(age=20)
for i in list:
print(i.id,i.name,i.age)
结果如下:
shell
3 wangwu 21
4 xiaohong 22
5 xiaoming 23
7.Q查询
q查询就是或关系查询
python
from .models import *
from django.db.models import Q
from django.http import HttpResponse
def fun_app1(request):
list = students1.objects.filter(Q(name="xiao") | Q(age=20))
for i in list:
print(i.id,i.name,i.age)
return HttpResponse("查询成功")
模型类函数有很多,具体可以参照官网
六、修改和删除
修改之前查看表内容
mysql
mysql> select * from my_students1;
+----+----------+------+
| id | name | age |
+----+----------+------+
| 1 | zhangsan | 20 |
| 2 | lisi | 20 |
| 3 | wangwu | 21 |
| 4 | xiaohong | 22 |
| 5 | xiaoming | 23 |
+----+----------+------+
5 rows in set (0.01 sec)
1.修改update()
修改views.py视图函数内容
c
from .models import *
from django.db.models import Q
from django.http import HttpResponse
def fun_app1(request):
# 先查询年龄等于20的结果集
list = students1.objects.filter(age=20)
# 然后直接修改结果集
list.update(age=30)
#在查询修改后的结果
list = students1.objects.filter(age=30)
for i in list:
print(i.id,i.name,i.age)
return HttpResponse("修改数据成功")
再次查看数据库内容,数据已经成功修改
mysql
mysql> select * from my_students1;
+----+----------+------+
| id | name | age |
+----+----------+------+
| 1 | zhangsan | 30 |
| 2 | lisi | 30 |
| 3 | wangwu | 21 |
| 4 | xiaohong | 22 |
| 5 | xiaoming | 23 |
+----+----------+------+
5 rows in set (0.00 sec)
2.删除delete()
shell
例子1:
list = students1.objects.filter(age=30)
list.delete()
例子2:
list = students1.objects.get(name='wangwu')
list.delete()
七、多表操作
1.一对多操作
1.1 创建my_publish表。
mysql
mysql> use mydatabase
mysql> create table my_publish(id int(10) primary key auto_increment,name varchar(20),addr varchar(50),email varchar(20));
mysql> desc my_publish;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(10) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
| email | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
1.2.在my_publish表中插入数据
mysql
insert into my_publish values(0,'苹果出版社','北京',123),(0,'西瓜出版社','南京',456);
mysql> select * from my_publish;
+------+-----------------+--------+-------+
| id | name | addr | email |
+------+-----------------+--------+-------+
| 1 | 苹果出版社 | 北京 | 123 |
| 2 | 西瓜出版社 | 南京 | 456 |
+------+-----------------+--------+-------+
2 rows in set (0.00 sec)
1.3.创建my_book表
mysql
create table my_book(id int(10) primary key auto_increment,title varchar(20),price double(5,2),publishDate datetime,publish_id int(10),foreign key(publish_id)
references my_publish(id));
查看创建的表结构
mysql
mysql> desc my_book;
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| id | int(10) | NO | PRI | NULL | auto_increment |
| title | varchar(20) | YES | | NULL | |
| price | double(5,2) | YES | | NULL | |
| publishDate | datetime | YES | | NULL | |
| publish_id | int(10) | YES | MUL | NULL | |
+-------------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
1.4 手动插入数据进行测试
mysql
mysql> insert into my_book values(0,"西游记",199.00,now(),1);
Query OK, 1 row affected (0.00 sec)
# 查看数据是否插入成功
mysql> select * from my_book;
+------+-----------+--------+---------------------+------------+
| id | title | price | publishDate | publish_id |
+------+-----------+--------+---------------------+------------+
| 1 | 西游记 | 199.00 | 2024-02-11 21:08:50 | 1 |
+------+-----------+--------+---------------------+------------+
1 row in set (0.00 sec)
1.5 建立模型类
编辑app1应用下的models.py文件
c
from django.db import models
# 创建my_publish表的模型类
class my_publish(models.Model):
class Meta:
db_table = 'my_publish' #这里的表名称一定要和数据库中表名保持一致
id = models.AutoField(max_length=10,primary_key=True)
name = models.CharField(max_length=20)
addr = models.CharField(max_length=50)
email = models.CharField(max_length=50)
# 创建my_book表的模型类
class my_book(models.Model):
class Meta:
db_table = 'my_book' # 这里的表名称一定要和数据库中表名保持一致
id = models.AutoField(max_length=10,primary_key=True)
title = models.CharField(max_length=20)
price = models.FloatField()
# auto_now_add 新增数据库数据库的时候才会触发这个时间,修改数据不会触发,修改要触发时间需要使用auto_now=True
publishDate = models.DateTimeField(auto_now_add=True)
#注意: publish 是外键,外键的名称django会自动补充上"_id".正好和数据库中的字段pubish_id字段对应上
publish = models.ForeignKey(my_publish,null=True,on_delete=models.SET_NULL)
1.6 使用视图查询my_book数据
这里没有直接对my_book表直接进行插入数据操作而是先查询,原因是先看上边的的模型类定义的是否正确
python
from .models import *
from django.db.models import Q
from django.http import HttpResponse
def fun_app1(request):
list = my_book.objects.all()
for i in list:
print(i.id,i.title,i.price,i.publishDate,i.publish_id)
return HttpResponse("查询数据成功")
1.7 使用视图插入数据
在app1应用下的视图函数
c
from .models import *
from django.http import HttpResponse
def fun_app1(request):
# 这里要注意,获取id时需要使用get,不能使用fiter,因为get返回的是结果,filter返回是查询对象集合
# 这里pk是自动指向my_publish的主键。pk是primary key的简写。在django中pk是固定写法
publish_id = my_publish.objects.get(pk=2)
my_book.objects.create(title="水浒传",price="88.00",publish=publish_id)
return HttpResponse("插入数据成功")
查看数据库数据如下:
mysql
mysql> select * from my_book;
+----+-----------+--------+---------------------+------------+
| id | title | price | publishDate | publish_id |
+----+-----------+--------+---------------------+------------+
| 1 | 西游记 | 199.00 | 2024-02-11 23:08:45 | 1 |
| 2 | 水浒传 | 88.00 | 2024-02-12 04:25:09 | 2 |
+----+-----------+--------+---------------------+------------+
2 rows in set (0.00 sec)-+
另外一种写法前边也介绍过了
c
from .models import *
from django.http import HttpResponse
def fun_app1(request):
publish_id = my_publish.objects.get(pk=2)
book1 = my_book(title="三国演义",price="188.00",publish=publish_id)
book1.save()
return HttpResponse("插入数据成功")
结果如下:
mysql
mysql> select * from my_book;
+----+--------------+--------+---------------------+------------+
| id | title | price | publishDate | publish_id |
+----+--------------+--------+---------------------+------------+
| 1 | 西游记 | 199.00 | 2024-02-11 23:08:45 | 1 |
| 2 | 水浒传 | 88.00 | 2024-02-12 04:25:09 | 2 |
| 3 | 三国演义 | 188.00 | 2024-02-12 04:30:24 | 2 |
+----+--------------+--------+---------------------+------------+