Django与数据库交互的实现


Posted in Python onJune 03, 2021

1 如何创建项目数据库

首先,在虚拟机数据库中建立一个与项目同名的数据库,方便管理。

(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):

Django与数据库交互的实现

由于需要操作mysql数据库,所以需要在虚拟环境中安装pymysql,注意:需要一定要在对应的虚拟环境中安装。

pip install mysql -i https://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)

这样我们就可以在前端接收数据后,直接添加入数据库

Django与数据库交互的实现

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数据时可以看的清楚一些。

Django与数据库交互的实现

上面是查询所有数据。那么如何查询一个数据呢?

4.2查询一个数据

def find_user(request):
	# 查询一个数据
    user = User.objects.get(id=1)
    print(user, type(user))
    return HttpResponse('查询成功')

Django与数据库交互的实现

这里需要注意的是,get方法是用来查询唯一数据,如果你输入的条件不是唯一的,会直接报错。那么查询多个数据?

4.3查询多条数据

def find_user(request):
    # 查询多条数据
    user_list = User.objects.filter(name=18)
    print(user_list, type(user_list))
    return HttpResponse('查询成功')

这里我们使用filter方法

Django与数据库交互的实现

这里返回的是一个集合对象(可迭代对象,即可被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('查询成功')

这样就能返回多条信息。

Django与数据库交互的实现

不仅如此,该对象还可以切片。

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查询一般用于逻辑查询

到此这篇关于Django与数据库交互的实现的文章就介绍到这了,更多相关Django 数据库交互内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python利用正则表达式排除集合中字符的功能示例
Oct 10 Python
Python编程pygame模块实现移动的小车示例代码
Jan 03 Python
django数据库migrate失败的解决方法解析
Feb 08 Python
Python读取数据集并消除数据中的空行方法
Jul 12 Python
python利用ffmpeg进行录制屏幕的方法
Jan 10 Python
python3.6数独问题的解决
Jan 21 Python
pyqt5 获取显示器的分辨率的方法
Jun 18 Python
python实现鸢尾花三种聚类算法(K-means,AGNES,DBScan)
Jun 27 Python
pycharm 批量修改变量名称的方法
Aug 01 Python
python 读取更新中的log 或其它文本方式
Dec 24 Python
如何给Python代码进行加密
Jan 10 Python
python自动打开浏览器下载zip并提取内容写入excel
Jan 04 Python
Python代码风格与编程习惯重要吗?
Jun 03 #Python
python 经纬度求两点距离、三点面积操作
Jun 03 #Python
如何使用PyCharm及常用配置详解
python for循环赋值问题
Jun 03 #Python
python批量创建变量并赋值操作
Jun 03 #Python
详解运行Python的神器Jupyter Notebook
Jun 03 #Python
python中如何对多变量连续赋值
You might like
php入门学习知识点二 PHP简单的分页过程与原理
2011/07/14 PHP
PHP实现通用alert函数的方法
2015/03/11 PHP
PHP常用的排序和查找算法
2015/08/06 PHP
php基于数组函数实现关联表的编辑操作示例
2017/07/04 PHP
详解Laravel5.6 Passport实现Api接口认证
2018/07/27 PHP
关于extjs4如何获取grid修改后的数据的问题
2013/08/07 Javascript
基于javascript滚动图片具体实现
2013/11/18 Javascript
js获得页面的高度和宽度的方法
2014/02/23 Javascript
js简单实现点击左右运动的方法
2015/04/10 Javascript
iScroll.js 使用方法参考
2016/05/16 Javascript
jQuery模拟select实现下拉菜单功能
2016/06/20 Javascript
浅谈js的html元素的父节点,子节点
2016/08/06 Javascript
Angular2-primeNG文件上传模块FileUpload使用详解
2017/01/14 Javascript
详解用Node.js实现Restful风格webservice
2017/09/29 Javascript
vue源码解析之事件机制原理
2018/04/21 Javascript
Vue 重置组件到初始状态的方法示例
2018/10/10 Javascript
async/await优雅的错误处理方法总结
2019/01/30 Javascript
如何在vue项目中嵌入jsp页面的方法(2种)
2020/02/06 Javascript
vue 解决uglifyjs-webpack-plugin打包出现报错的问题
2020/08/04 Javascript
python中mechanize库的简单使用示例
2014/01/10 Python
python登录pop3邮件服务器接收邮件的方法
2015/04/30 Python
python图像常规操作
2017/11/11 Python
运动检测ViBe算法python实现代码
2018/01/09 Python
Python使用pip安装报错:is not a supported wheel on this platform的解决方法
2018/01/23 Python
python3爬取各类天气信息
2018/02/24 Python
python取数作为临时极大值(极小值)的方法
2018/10/15 Python
numpy.ndarray 实现对特定行或列取值
2019/12/05 Python
使用python-opencv读取视频,计算视频总帧数及FPS的实现
2019/12/10 Python
Python属性和内建属性实例解析
2020/01/14 Python
解决pycharm中导入自己写的.py函数出错问题
2020/02/12 Python
css3动画效果抖动解决方法
2018/09/03 HTML / CSS
广告设计专业自荐信范文
2013/11/14 职场文书
物业管理毕业生的自我评价
2014/02/17 职场文书
股指期货心得体会
2014/09/10 职场文书
2016高一新生军训心得体会
2016/01/11 职场文书
解决pytorch-gpu 安装失败的记录
2021/05/24 Python