Django 数据库交互 Django与数据库交互的实现
小白罢了 人气:01 如何创建项目数据库
首先,在虚拟机数据库中建立一个与项目同名的数据库,方便管理。
(django_test) bd@DF:~$ mysql -u admin -p
输入密码,进入数据库后。
mysql> SHOW DATABASES;
查看当前所有已有的数据库,然后创建数据库。
mysql> CREATE DATABASE 'django_test';
就会有一个名为‘django_test'的数据库。
+--------------------+ | Database | +--------------------+ | information_schema | | django_test | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.10 sec)
2 进行数据库与django的交互
有了数据库之后,我们需要把这个库配置到项目中,进行关系绑定。
首先在settings.py文件中的DATABASES一项:
DATABASES = { 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 'ENGINE': 'django.db.backends.mysql', # 数据库引擎 'NAME': 'django_test', # 哪一个数据库 'USER': 'admin', # 用户 'PASSWORD': 'yourpassword', # 数据库密码 'HOST': '127.0.0.1', # 数据库服务器IP 'PORT': '3306' # 数据库端口(需要去ubuntu中设置端口转发,虚拟机的端口是3306,我们直接转发到本地3306) } }
将默认的配置注释掉,然后带上自己的数据库信息.端口转发(ubuntu):
由于需要操作mysql数据库,所以需要在虚拟环境中安装pymysql,注意:需要一定要在对应的虚拟环境中安装。
pip install mysql -i http://pypi.douban.com/simple
使用豆瓣源会快一些。然后pip list 查看自己是否已经有pymysql。有了之后,进入项目总目录下的__init__.py文件。
import pymysql pymysql.install_as_MySQLdb()
添加两行代码,完成映射的导入。然后去我们需要进行数据库交互的app中的models.py.
from django.db import models # Create your models here. class User(models.Model): # id = models.AutoField(primary_key=True) # 主键字段不需要我们自己写 name = models.CharField(max_length=30) age = models.IntegerField(null=True) sex = models.IntegerField(null=True) city = models.CharField(max_length=30, null=True) note = models.TextField(null=True) create_time = models.DateTimeField(auto_now_add=True) update_time = models.DateTimeField(auto_now=True)
这里我们定义了很多项,然后对应的数据类型是需要注意的(根据你定义的项的数据类型来),括号里面的限定信息也需要注意。数据类型:
类型 | 说明 |
---|---|
AutoField | 自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性 |
BooleanField | 布尔字段,值为True或False |
NullBooleanField | 支持Null、True、False三种值 |
CharField | 字符串,参数max_length表示最大字符个数 |
TextField | 大文本字段,一般超过4000个字符时使用 |
IntegerField | 整数 |
DecimalField | 十进制浮点数, 参数max_digits表示总位数, 参数decimal_places表示小数位数 |
FloatField | 浮点数 |
DateField | 日期, 参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add和auto_now是相互排斥的,组合将会发生错误 |
TimeField | 时间,参数同DateField |
DateTimeField | 日期时间,参数同DateField |
FileField | 上传文件字段 |
ImageField | 继承于FileField,对上传的内容进行校验,确保是有效的图片 |
限定条件:
选项 | 说明 |
---|---|
null | 如果为True,表示允许为空,默认值是False |
blank | 如果为True,则该字段允许为空白,默认值是False |
db_column | 字段的名称,如果未指定,则使用属性的名称 |
db_index | 若值为True, 则在表中会为此字段创建索引,默认值是False |
default | 默认值 |
primary_key | 若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用 |
unique | 如果为True, 这个字段在表中必须有唯一值,默认值是False |
max_length | 字段长度限制 |
DateField.auto_now | 修改数据时,更新时间,使用save方法才会有用 |
DateField.auto_now_add | 第一次添加会将当前时间设置进去,修改不会 |
在完成数据的导入之后,我们就要在虚拟机中进行迁移。移动到项目目录下。
python manage.py makemigrations
命令后面可以跟app名称,指定对某个app的模型进行映射,如果没有写,就所有的app都回去创建映射文件。再次之前,你必须保证你的app都在settings里面注册了。
在迁移完之后,我们需要将迁移的数据提交给数据库(在虚拟机中且在目录下):
python manage.py migrate
我们可以这样理解,迁移是将我们在user类中定义的数据项转化为create table这样的mysql语句,然后就是将语句提交到数据库中创建表。
创建完成后,我们在数据库中查看是否完成操作:
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | django_test | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec) mysql> use django_test; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; +-----------------------+ | Tables_in_django_test | +-----------------------+ | django_migrations | | six_user | +-----------------------+ 2 rows in set (0.00 sec) mysql> describe six_user; +-------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(30) | NO | | NULL | | | age | int(11) | YES | | NULL | | | sex | int(11) | YES | | NULL | | | note | longtext | YES | | NULL | | | create_time | datetime(6) | NO | | NULL | | | update_time | datetime(6) | NO | | NULL | | | city | varchar(30) | YES | | NULL | | +-------------+-------------+------+-----+---------+----------------+ 8 rows in set (0.00 sec)
这里我们首先show databases;查看库,再进入我们的项目数据库,选择six_user查看表格。完成实现数据表创建操作。
如果我们需要修改表,那么我们只需要修改模型类就可以了,如果我们需要在模型类中添加一个字段,那么我们不能直接增加,因为增加一个不可为空的字段会存在一个逻辑错误。即添加一个本身为空(添加进去的时候是空的)的不可为空字段是不被允许的,所以我们需要在括号中添加null=True。
如上面模型类的city字段,添加完成后,进行迁移和提交即可,就是上面两个步骤,删除也是一样的,也就是说,只要是更新模型类,都需要上面2个步骤。
3 添加数据
如果我们需要添加数据,我们试一下
from django.http import HttpResponse, HttpResponseNotFound from django.shortcuts import redirect, render from .models import User # Create your views here. def add_user(request): # 方法一 # user = User(name='zjj', age=18) # user.save() # 使用save方法保存提交数据 # return HttpResponse('添加成功') # 方法二 # user = User() # user.name = 'zj' # user.age = 18 # user.save() # return HttpResponse('添加成功') # 方法三 # User.objects.create(name='z', age=8) # return HttpResponse('添加成功') # 方法四 get_or_create会判断有没有传入的数据(指完全一致的数据),如果有则不创建,只获取,如果没有则创建,并获取,返回一个元组。 user, flag = User.objects.get_or_create(name='z1', age=10) message = '添加成功' if not flag: message = '已有数据' print(user.name, user.create_time) return HttpResponse(message)
这里我们首先需要引入models类中我们定义的User类,然后通过对User类实例化进行添加,以上举例了四种方法,前两种方法都需要使用save方法,后面两种是调用对象的方法直接添加数据,较为方便,这里需要讲一下最后一个方法,这个方法会判断传入数据,如果没有传入数据,就会首先创建,然后获取该数据,返回一个True,这里我在上面print了几条数据,可以去测试一下。如果是重复数据,就会不创建,返回数据,加一个False。那么我们在这里进行一个拆包,获取两个参数,然后做一个判断,这样就可以进行页面的信息传递。
mysql> SELECT * FROM `six_user`; +----+------+------+------+------+----------------------------+----------------------------+------+ | id | name | age | sex | note | create_time | update_time | city | +----+------+------+------+------+----------------------------+----------------------------+------+ | 1 | zjj | 18 | NULL | NULL | 2021-03-10 21:40:18.246543 | 2021-03-10 21:40:18.246564 | NULL | | 2 | zj | 18 | NULL | NULL | 2021-03-10 21:44:36.590347 | 2021-03-10 21:44:36.590365 | NULL | | 3 | z | 8 | NULL | NULL | 2021-03-10 21:46:37.315176 | 2021-03-10 21:46:37.315195 | NULL | | 4 | z1 | 10 | NULL | NULL | 2021-03-10 21:56:20.559386 | 2021-03-10 21:56:20.559421 | NULL | +----+------+------+------+------+----------------------------+----------------------------+------+ 4 rows in set (0.00 sec)
然后还有一种方法就是在前端页面添加数据,然后后端接收后添加入数据库。
第一步,在路由中添加接收信息:
from django.contrib import admin from django.urls import path from . import views urlpatterns = [ path(r'add_user/<name>/<age>', views.add_user) ]
视图函数中:
def add_user(request, name, age): user, flag = User.objects.get_or_create(name=name, age=age) message = '添加成功' if not flag: message = '已有数据' print(user.name, user.create_time) return HttpResponse(message)
这样我们就可以在前端接收数据后,直接添加入数据库
mysql> SELECT * FROM `six_user`; +----+------+------+------+------+----------------------------+----------------------------+------+ | id | name | age | sex | note | create_time | update_time | city | +----+------+------+------+------+----------------------------+----------------------------+------+ | 1 | zjj | 18 | NULL | NULL | 2021-03-10 21:40:18.246543 | 2021-03-10 21:40:18.246564 | NULL | | 2 | zj | 18 | NULL | NULL | 2021-03-10 21:44:36.590347 | 2021-03-10 21:44:36.590365 | NULL | | 3 | z | 8 | NULL | NULL | 2021-03-10 21:46:37.315176 | 2021-03-10 21:46:37.315195 | NULL | | 4 | z1 | 10 | NULL | NULL | 2021-03-10 21:56:20.559386 | 2021-03-10 21:56:20.559421 | NULL | | 5 | zjjj | 21 | NULL | NULL | 2021-03-10 22:06:47.200072 | 2021-03-10 22:06:47.200101 | NULL | +----+------+------+------+------+----------------------------+----------------------------+------+ 5 rows in set (0.00 sec)
4 查找数据
4.1查找所有数据
查找数据方法,我们先定一个函数来试试看:
def find_user(request): # 查询所有数据 user_list = User.objects.all() print(user_list) return HttpResponse('查询成功')
记得添加路由,然后我们在模型类下使用魔法方法修改print方法
def __str__(self): return 'id=%s, name=%s, age=%s, city=%s, note=%s' % (self.id, self.name, self.age, self.city, self.note)
那么我们在print数据时可以看的清楚一些。
上面是查询所有数据。那么如何查询一个数据呢?
4.2查询一个数据
def find_user(request): # 查询一个数据 user = User.objects.get(id=1) print(user, type(user)) return HttpResponse('查询成功')
这里需要注意的是,get方法是用来查询唯一数据,如果你输入的条件不是唯一的,会直接报错。那么查询多个数据?
4.3查询多条数据
def find_user(request): # 查询多条数据 user_list = User.objects.filter(name=18) print(user_list, type(user_list)) return HttpResponse('查询成功')
这里我们使用filter方法
这里返回的是一个集合对象(可迭代对象,即可被for循环)。
def find_user(request): # 查询多条数据 user_list = User.objects.filter(age=18) for user in user_list: print(user) # print(user_list, type(user_list)) return HttpResponse('查询成功')
这样就能返回多条信息。
不仅如此,该对象还可以切片。
def find_user(request): # 查询多条数据 user_list = User.objects.filter(age=18) # for user in user_list: # print(user) # print(user_list, type(user_list)) print(user_list[0:1]) return HttpResponse('查询成功')
还可以转型
def find_user(request): # 查询多条数据 user_list = User.objects.filter(age=18) # for user in user_list: # print(user) # print(user_list, type(user_list)) # print(user_list[0:1]) print(list(user_list)) return HttpResponse('查询成功')
4 更新数据
更新数据的步骤就是先获得到你要修改的数据,然后对其进行重新赋值
4.1获取数据
from django.shortcuts import render from django.http import HttpResponse from six.models import User from django.db.models import Count, Avg, Min, Max, Sum, F, Q # Create your views here. # 常用的查询方法 def find(request): # 获取所有数据 rs = User.objects.all() # 获取第一条数据 rs = User.objects.first() # 获取最后一条方法 rs = User.objects.last() # 获取指定条件的多条数据 rs = User.objects.filter(age=18) # 获取唯一的一条数据,一般的get返回对象具有唯一性(一般用id来查),如果有多个就会报错,可以用try来处理 rs = User.objects.get(id=3)
这里的方法很多,可根据需要来
4.2对数据排序
# 对结果排序 rs = User.objects.order_by('age') # 正序,从小到大 rs = User.objects.order_by('-age') # 倒序,从大到小 # 多项排序 rs = User.objects.order_by('age', '-id') # 获取当前查询到的数据的总数,只需要在查找后面加上count方法即可 rs = User.objects.filter(age=28).count() # 将返回的QuerySet中的Model转换成字典,转换成字典之后,我们可以进行迭代用键取值 rs = User.objects.all().values() for i in rs: print(i['name']) print(rs)
4.3查询条件
# 常用查询条件 # 相当于WHERE语句后面的提交,传给查询方法的一些参数 # 语法规则 :字段名__条件, 注意是两个下划线 # 等于 rs = User.objects.filter(age=18) # 包含 模糊查询 rs = User.objects.filter(name__contains='j') # 大于 rs = User.objects.filter(age__gt=18) # 大于等于 rs = User.objects.filter(age__gte=18) # 小于 rs = User.objects.filter(age__lt=18) # 小于等于 rs = User.objects.filter(age__lte=18) # 判断是否为空 rs = User.objects.filter(city__isnull=True) # 以什么开始 rs = User.objects.filter(name__startwith='z') # 以什么结尾 rs = User.objects.filter(name__endwith='1') # 多个条件 成员所属,是否在我们给的列表条件中 rs = User.objects.filter(name__in=['zj', 'zjj', 'zjjjj']) # 范围 包含开头和结尾 rs = User.objects.filter(age__range=(18, 28))
4.4聚合查询
Count, Avg, Min, Max, Sum主要有这些方法
from django.db.models import Count, Avg, Min, Max, Sum, F, Q # 可以使用聚合查询进行聚合查询, Count,Avg, Max, Min, Sum.这是需要导入的 # aggregate()是QuerySet的一个终止语句,返回的是一个包含键值对的字典 # 统计条数 rs = User.objects.all().aggregate(Count('age')) # 求年龄平均值 rs = User.objects.all().aggregate(Avg('age')) # 求年龄最大值 rs = User.objects.all().aggregate(Max('age')) # 求年龄最小值 rs = User.objects.all().aggregate(Min('age')) # 年龄求和 rs = User.objects.all().aggregate(Sum('age')) # 可以修改key的值 以上的返回值都是一个键值对,我们可以更改key的值 rs = User.objects.all().aggregate(ageSum=Sum('age'))
4.5分组查询
# 分组查询 # 调用的QuerySet中每个对象都生成一个独立的统计值 # 拿出需要分组的字段 values方法是获得括号里,在数据库中所有该属性的值,并返回键值对类型的字典 rs = User.objects.values('age') # 对age这个字段进行分组 ,这里使用的计数函数,即返回的字典里显示该age的个数的键值对 rs = rs.annotate(count=Count('age')) # 或者使用这个方法 rs = User.objects.values('age').annotate(count=Count('age'))
F和Q查询
from django.db.models import F, Q # F查询 也需要导入 # 给User表中的所有人加一岁(+1), 减一岁就-1 rs = User.objects.all().update(age=F('age') + 1) # Q查询 # 如果需要执行更加复杂的查询,可以使用Q对象 # & (and) | (or) ~ (not) # 查询名字尾zj或者年龄为18的用户 rs = User.objects.filter(Q(name='zj') | Q(age=18)) # 查询名字为zjjj,并且年龄不等于28 rs = User.objects.filter(Q(name='zjjj') & ~Q(age=28)) print(rs) return HttpResponse('查找成功')
Q查询一般用于逻辑查询
加载全部内容