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基于PycURL实现POST的方法
Jul 25 Python
使用PyCharm配合部署Python的Django框架的配置纪实
Nov 19 Python
Python读取和处理文件后缀为.sqlite的数据文件(实例讲解)
Jun 27 Python
详解python上传文件和字符到PHP服务器
Nov 24 Python
Selenium定位元素操作示例
Aug 10 Python
django如何自己创建一个中间件
Jul 24 Python
python中的TCP(传输控制协议)用法实例分析
Nov 15 Python
Python enumerate内置库用法解析
Feb 24 Python
在django admin详情表单显示中添加自定义控件的实现
Mar 11 Python
pycharm通过anaconda安装pyqt5的教程
Mar 24 Python
python同时遍历两个list用法说明
May 02 Python
python接口自动化框架实战
Dec 23 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
PHP5+UTF8多文件上传类
2008/10/17 PHP
PHP获取一年有几周以及每周开始日期和结束日期
2015/08/06 PHP
Apache无法自动跳转却显示目录的解决方法
2020/11/30 PHP
自制PHP框架之设计模式
2017/05/07 PHP
从父页面读取和操作iframe中内容方法
2009/07/25 Javascript
javascript parseInt() 函数的进制转换注意细节
2013/01/08 Javascript
JavaScript作用域链使用介绍
2013/08/29 Javascript
JsRender for index循环索引用法详解
2014/10/31 Javascript
jQuery选择器源码解读(八):addCombinator函数
2015/03/31 Javascript
Javascript技术难点之apply,call与this之间的衔接
2015/12/04 Javascript
Bootstrap按钮组件详解
2016/04/26 Javascript
Bootstrap每天必学之工具提示(Tooltip)插件
2016/04/26 Javascript
基于WebUploader的文件上传js插件
2016/08/19 Javascript
Node.js包管理器Yarn的入门介绍与安装
2016/10/17 Javascript
使用Bootstrap Tabs选项卡Ajax加载数据实现
2016/12/23 Javascript
利用jquery正则表达式在页面验证url网址输入是否正确
2017/04/04 jQuery
vue几个常用跨域处理方式介绍
2018/02/07 Javascript
在vue-cli搭建的项目中增加后台mock接口的方法
2018/04/26 Javascript
JavaScript中的回调函数实例讲解
2019/01/27 Javascript
详解auto-vue-file:一个自动创建vue组件的包
2019/04/26 Javascript
为python设置socket代理的方法
2015/01/14 Python
Python正确重载运算符的方法示例详解
2017/08/27 Python
解决python3读取Python2存储的pickle文件问题
2018/10/25 Python
Python 从一个文件中调用另一个文件的类方法
2019/01/10 Python
python scrapy重复执行实现代码详解
2019/12/28 Python
Python破解BiliBili滑块验证码的思路详解(完美避开人机识别)
2020/02/17 Python
python GUI库图形界面开发之PyQt5布局控件QGridLayout详细使用方法与实例
2020/03/06 Python
浅析Python 责任链设计模式
2020/09/11 Python
DHC中国官方购物网站:日本通信销售No.1化妆品
2016/08/20 全球购物
一年级学生评语大全
2014/04/21 职场文书
小学教师师德承诺书
2014/05/23 职场文书
模特大赛策划方案
2014/05/28 职场文书
大学毕业生管理学求职信
2014/09/01 职场文书
2015年售后服务工作总结
2015/04/25 职场文书
聊一聊Redis与MySQL双写一致性如何保证
2021/06/26 Redis
Python标准库pathlib操作目录和文件
2021/11/20 Python