Python Django 之各种数据库连接及基本操作

462 阅读9分钟

Anaconda的基本介绍和使用及常用命令
使用anaconda+Pycharm搭建Django项目(一)
使用anaconda+命令搭建Django项目(一)
使用anaconda+Pycharm搭建Django项目-模板使用和前后端交互(二)
使用anaconda+Pycharm搭建Django项目-与SQLite数据库交互(三)
Python Django 之各种数据库连接及基本操作

一、引言

Django是一个高级Python Web框架,它使得开发Web应用程序变得更加快速和简单。本文我们主要介绍使用Django连接数据库。Django中默认支持的数据库有PostgreSQLMySQLOracleSQLiteMariaDB

Django框架内部为我们提供了ORM框架,为不同的数据库提供了统一接口,使我们可以在不改变代码的情况下轻松切换数据库引擎。

二、Django提供的ORM能做什么?

2.1 ORM能做什么

ORM在表层数据层面,可以简化我们的操作。但是对于数据库本身(如数据库实例)需要我们自己手动去创建。

2.1.1 对于数据库表层面

  1. 创建表:通过定义模型(Model)并执行makemigrationsmigrate命令来创建。
  2. 修改表:修改模型后,再次执行makemigrationsmigrate来更新表结构。
  3. 删除表:删除模型文件中的模型类,并执行makemigrationsmigrate

2.1.2 对于数据库操作

Django ORM提供了简单直观的API来操作表中的数据:我们可以轻松进行表中数据的增、删、改、查。

2.2 ORM的优势

Django提供的ORM框架让我们操作数据库更加便利直观,它的核心优势包括如下:

  1. 抽象层Django ORM为不同的数据库提供了统一的接口,你可以在不改变代码的情况下切换数据库引擎(如从SQLite切换到PostgreSQL)。
  2. 安全性:自动处理SQL语句的生成,减少了SQL注入的风险。
  3. 简便性:无需编写复杂的SQL语句,通过Python代码即可完成数据库操作。
  4. 灵活性:提供了丰富的查询方法和字段类型,满足各种业务需求。

三、Django连接数据库步骤

DjangoORM框架支持多种数据库操作,在这里我们以mysql为例,进行演示。不同数据库的数据库操作都是由ORM进行完成,只是他们的配置文件会略有不同,我们在文章最后会列出来常用的数据库连接配置。

连接数据库的主要步骤

  1. 下载相关数据库驱动:例如 mysql(pip install mysqlclient)
  2. 配置数据库信息:在settings.py文件中找到DATABASES配置
  3. 创建模型:模型是数据库表的映射
  4. 迁移数据库:在创建或修改模型后,你需要应用迁移来更新数据库结构。
  5. 使用模型: 使用模型来操作数据库

3.1 下载MySql数据库驱动

pip install mysqlclient

3.2 配置数据库信息

settings.py文件中找到DATABASES配置。

# MySQL
DATABASES = {
'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'test',  # 数据库名
        'USER': 'root',  # 登录用户名
        'PASSWORD': 'pwd',  # 登录用户名密码
        'HOST': '127.0.0.1',  # mysql服务器ip
        'PORT': '3306'  # mysql服务器端口
    }
}

ENGINE: 指定了数据库引擎。
NAME: 指定了数据库名称(如果是sqlite,这里要写数据库文件的路径)
USER: 指定了数据库用户名
PASSWORD: 指定了数据库密码
HOST: mysql服务器ip
PORT: mysql服务器端口

3.3 创建模型

在 Django 中,模型是数据库表的映射。 在应用层(通过python manage.py startapp myapp命令创建)app的models.py中定义一个模型。

from django.db import models

# Create your models here.
class Student(models.Model):
    name = models.TextField(max_length=100)  # 通常名字用CharField更合适
    age = models.IntegerField()  # 年龄应该是整数
    description = models.TextField()

3.4 迁移数据库

在创建或修改模型后,需要应用迁移来更新数据库结构。

3.4.1 迁移数据库文件

在各个应用的migrations中自动生成sql的映射文件。

python manage.py makemigrations
3.4.2 同步表结构

将最新的sql同步到数据库中。

python manage.py migrate

执行完这一步以后,django相关数据库表会创建到指定数据库中,我们自定义的Student模型所属的表也会根据模型,创建到数据库中。 image.png

3.5 使用模型,完成增删改查

可以使用 Django 的 ORM 来操作数据库。在这里我们演示新增与查询。

3.5.1 打开 app/views.py 文件,并添加接口insertAndGetStudent
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from .models import Student

@csrf_exempt
def insertAndGetStudent(request):
    if request.method == 'POST':
        name = request.POST.get("name")
        age = request.POST.get("age")
        try:
            age = int(age)  # 将年龄转换为整数
        except ValueError:
            return HttpResponse("Invalid age. Please enter a valid integer for age.")
        description = request.POST.get("description")
        student = Student(name=name, age=age, description=description)
        # 新增
        student.save()
        # 查询
        students = Student.objects.all()
        return render(request, 'student.html', {'data': students})
    else:
        students = Student.objects.all()
        return render(request, 'student.html', {'data': students})

在这里,新增有两种方式,通过实例化对象的save方法或者通过ORM提供的objects提供的create方法来实现上述代码使用的是save方法。
通过实例化对象的save方法:

student = Student(name="张三", age=18, description="学生描述")
student.save()

通过ORM提供的objects提供的create方法

student = models.Student.objects.create(name="张三", age=18, description="学生描述")
3.5.2 打开app/urls.py文件,添加url
path('student/', views.insertAndGetStudent),
3.5.3 在templates中添加student页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Student</title>
</head>
<body>
    <form action="/student/" method="post"></br>
        <!-- 用于防止跨站请求伪造的。确保在表单中包含这个令牌-->
        {% csrf_token %}
        学生姓名: <input type="text" name="name">
        年龄:<input type="text" name="age">
        描述:<input type="text"  name="description"></textarea>
        <input type="submit" value="提交">
        <hr >
        <h2>学生列表</h2>
        <table style="border: 1px">
        <tr>
            <th>学生姓名</th>
            <th>年龄</th>
            <th>描述</th>
        </tr>
        {% for item in data %}
            <tr>
                <td>{{ item.name }}</td>
                <td>{{ item.age }}</td>
                <td>{{ item.description }}</td>
            </tr>
        {% endfor %}
          </table>
</form>
</body>
</html>
3.5.4 运行项目
python .\manage.py runserver
3.5.5 运行结果

image.png

附录一:ORM操作的API

ORM 提供了两种方式来实现对数据的操作:
第一种:使用ORM 提供的 objects 提供的方法来实现对数据的相关操作。
第二种:通过实例化对象的相关方法来实现对数据的相关操作。

一般我们更推荐使用提供的objects提供的方法来操作数据。下面列举一些常用操作。

新增

方法 描述 举例
create(推荐) 使用ORM提供的objects提供的create()进行新增数据 student=models.Student.objects.create
(name="张三",age=18,description="学生描述")
save 使用实例化对象的**save()**方法进行新增数据 student=Student(name="张三",age=18,description="学生描述")student.save()

删除

方法 描述 举例
delete(推荐) 使用QuerySet类型数据.delete()。

返回值:元组,第一个元素为受影响的行数。
`student=models.Student.objects
.filter(id__in=[1,2]).delete()`
对象.delete() 使用模型类的 对象.delete()。

返回值:元组,第一个元素为受影响的行数。
`student=models.Student.objects.
filter(id=8).first().delete()`

注意

  • a.Django删除数据时,会模仿SQL约束ONDELETECASCADE的行为,也就是删除一个对象时也会删除与它相关联的外键对象。
  • b.delete()方法是QuerySet数据类型的方法,但并不适用于Manager本身。也就是想要删除所有数据,不能不写all。
python student=models.Student.objects.delete() #报错
student=models.Student.objects.all().delete() #删除成功

修改

方法 描述 举例
update(推荐) QuerySet类型数据.update(字段名=更改的数据)

返回值:整数,受影响的行数
student = models.Student.objects.
filter(id__in=[7,8]).update(price=888)
save 使用模型类的 对象.save()。

返回值:编辑的模型类的对象。
student=models.Student.objects.
filter(id=7).first()student.age=18student.save()

查询

方法 描述 举例
all 使用 all() 方法来查询所有内容 models.Student.objects.all()
filter filter() 方法用于查询符合条件的数据 student=models.Student.objects
.filter(id=3)
exclude 用于查询不符合条件的数据 models.Student.objects
.exclude(name="张三")
get 方法用于查询符合条件的返回模型类的对象符合条件的对象只能为一个,如果符合筛选条件的对象超过了一个或者没有一个都会抛出错误 models.Student.objects
.get(name="张三")
order_by 对查询结果进行排序 升序:models.Student.objects
.order_by("age")
降序:models.Student.objects
.order_by("-age")
reverse 对查询结果进行反转 models.Student.objects
.order_by("age").reverse()
count 查询数据的数量返回的数据是整数 查询所有数据的数量:
models.Student.objects.count()
查询符合条件数据的数量:
models.Student.objects
.filter(age=18).count()
first 返回所有数据的第一条数据,也可以是返回符合条件的数据的第一条数据 models.Student.objects.first()
last 返回所有数据的最后一条数据,也可以是返回符合条件的数据的最后一条数据 models.Student.objects.last()
exists 判断查询的结果QuerySet列表里是否有数据,返回true或false。

不可以判断整数型结果或模型对象(count(),first()等查询的结果)
models.Student.objects.exists()
values 用于查询部分字段的数据,返回的是QuerySet类型数据,类似于list,里面不是模型类的对象,而是一个可迭代的字典序列,字典里的键是字段,值是数据。 students=models.Student.objects
.values("name","age")
结果:name:students[0]["name"]
values_list 查询部分字段的数据,返回的是QuerySet类型数据,类似于list,里面不是模型类的对象,而是一个个元组,元组里放的是查询字段对应的数据。 students=models.Student.objects
.values_list("name","age")

结果:name:student[0][0]
distinct 用于对数据进行去重,返回的是QuerySet类型数据。distinct()一般是联合values或者values_list使用 models.Student.objects
.values_list("name","age").distinct()
对查询结果为模型类的对象去重没有意义,
因为每个对象都是一个不一样的存在。
filter的模糊查询 基于双下划线的模糊查询 (filter中运算符号只能使用等于号=,不能使用大于号>,小于号<,等等其他符号。
__in用于读取区间,=号后面为列表。
__gt大于号,=号后面为数字。
__gte大于等于,=号后面为数字。
__lt 小于,=号后面为数字。
__lte 小于等于,=号后面为数字。
__range 在...之间,左闭右闭区间,=号后面为两个元素的列表。
__contains 包含,=号后面为字符串。
__icontains 不区分大小写的包含,=号后面为字符串。
__startswith 以指定字符开头,=号后面为字符串。
__endswith 以指定字符结尾,=号后面为字符串。
__year 是DateField数据类型的年份,=号后面为数字。
__month 是DateField数据类型的月份,=号后面为数字。
__day 是DateField数据类型的天数,=号后面为数字。)
models.Student.objects
.filter(age__in=[18,20,25])

附录二:不同数据库的相关配置

一、SQLite

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3', # 数据库文件目录地址
    }
}

二、MySQL

DATABASES = {
'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'dbname',  #数据库名
        'USER': 'root',  #登录用户名
        'PASSWORD': 'pwd',  # 登录用户名密码
        'HOST': '127.0.0.1',  # mysql服务器ip
        'PORT': '3306'  # mysql服务器端口
    }
}

三、Oracle

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.oracle",
        "NAME": "xe",
        "USER": "a_user",
        "PASSWORD": "a_password",
        "HOST": "dbprod01ned.mycompany.com",
        "PORT": "1540",
    }
}

四、PostgreSQL

DATABASES = {
'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'dbname',  #数据库名
        'USER': 'root',  #登录用户名
        'PASSWORD': 'pwd',  # 登录用户名密码
        'HOST': '127.0.0.1',  # mysql服务器ip
        'PORT': '3306'  # mysql服务器端口
    }
}

附录三:不同数据的相关驱动

要将SQL语句在数据库服务端实行,需要安装各个数据库的客户端。

数据库 客户端驱动
PostgreSQL psycopg或psycopg2
MySQL pymysql或mysqlclient
Oracle oracledb或cx\_oracle