<学习笔记>从零开始自学Python-之-web应用框架Django(六)Django模型

       前面我们已经学习了Django的MTV模式中的 T(Template模板)和 V(View视图),现在我们就来看看这个 M(Model模型)

        对大部分的Web 应用程序而言,视图逻辑经常需要与数据库交互。在数据库驱动型网站中,网站连接数据库服务器,从中检索数据,然后在网页中把数据显示出来。此外,可能还会提供让访客自行填充数据库的方式。

Django 对各种数据库提供了很好的支持,包括:PostgreSQL、MySQL、SQLite、Oracle。

Django 为这些数据库提供了统一的调用API。 我们可以根据自己业务需求选择不同的数据库。

1、模型(model)的概念

        Django 模型是使用 Python 代码对数据库中数据的描述,是数据的结构,等效于 SQL 中的 CREATE TABLE 语句,不过是用 Python 代码而非 SQL 表述的,而且不仅 包含数据库列的定义。 Django 通过模型在背后执行 SQL,返回便利的 Python 数据结构,表示数据库表中的行。

Django 还通过模型表示 SQL 无法处理的高层级概念。

Django 模型使用自带的 ORM。

对象关系映射(Object Relational Mapping,简称 ORM )用于实现面向对象编程语言里不同类型系统的数据之间的转换。

ORM 在业务逻辑层和数据库层之间充当了桥梁的作用。

ORM 是通过使用描述对象和数据库之间的映射的元数据,将程序中的对象自动持久化到数据库中。

使用 ORM 的好处:

  • 提高开发效率。
  • 不同数据库可以平滑切换。

使用 ORM 的缺点:

  • ORM 代码转换为 SQL 语句时,需要花费一定的时间,执行效率会有所降低。
  • 长期写 ORM 代码,会降低编写 SQL 语句的能力。

ORM 解析过程:

  • ORM 会将 Python 代码转成为 SQL 语句。
  • SQL 语句通过 pymysql 传送到数据库服务端。
  • 在数据库中执行 SQL 语句并将结果返回。

ORM 对应关系表:

2、数据库配置

实际上,Django有自带的数据库引擎,打开setting.py,可以看到

# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

这里sqlite3就是默认的数据库引擎,一般小型化的网站可以直接用这个。

当然我们也可以配置别的数据库,以MySQL为例,配置数据库:

a) 创建 MySQL 数据库( ORM 无法操作到数据库级别,只能操作到数据表)语法:

create database 数据库名称 default charset=utf8; # 防止编码问题,指定为 utf8

例如我们创建一个名为 school 的数据库,编码指定为 utf8:

create database school default charset=utf8;  

b)我们在项目的 settings.py 文件中找到 DATABASES 配置项,将其信息修改为:

DATABASES = { 
    'default': 
    { 
        'ENGINE': 'django.db.backends.mysql',    # 数据库引擎
        'NAME': 'school', # 数据库名称
        'HOST': '127.0.0.1', # 数据库地址,本机 ip 地址 127.0.0.1 
        'PORT': 3306, # 端口 
        'USER': 'root',  # 数据库用户名
        'PASSWORD': '1234', # 数据库密码
    }  
}

c)接下来,告诉 Django 使用 pymysql 模块连接 mysql 数据库:

# 在与 settings.py 同级目录下的 __init__.py 中引入模块和进行配置
import pymysql
pymysql.install_as_MySQLdb()

3、定义模型

Django 规定,如果要使用模型,必须要创建一个 app。

我们使用以下命令创建一个 classManage 的 app:

django-admin startapp classManage

然后打开外层newweb文件夹,会发现多了一个classManage的文件夹(和内层newweb同级别)

打开文件夹,里面的文件目录如下:

打开其中的models.py文件,默认的代码如下:

from django.db import models

# Create your models here.

 现在我们可以在里面创建我们自己的模型了。比如我们想创建一个学生的模型,用来存放学生的数据,比如姓名、年龄、性别、成绩等等

from django.db import models

# Create your models here.

class Student(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=20)
    age = models.IntegerField(blank=True)
    sex = models.CharField(max_length=10)
    score = models.IntegerField (blank=True,default=0)
    skill = models.IntegerField(default=100)

以上的类名代表了数据库表名,且继承了models.Model,类里面的字段代表数据表中的字段(name),数据类型则有CharField(相当于varchar)、IntegerField(相当于INT) ,DateField(相当于datetime)等等,还有一般sql数据库没有的 EmailField (电子邮件数据类型)等。

primary_key参数表示主键, max_length 参数限定长度,default 参数设定默认值,blank参数设定数据可否为空等等。

4、安装模型

模型定义好后,还不能马上使用,要先在setting.py中注册APP:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'classManage',    #这里添加新创建的app
]

INSTALLED_APPS 中的各个应用通过完整的 Python 路径表示,即点分包路径,直到应用所在的包。在设置文件 中激活 Django 应用之后,可以在数据库中创建表了。首先,运行下述命令,验证模型:

python manage.py check

check 命令运行 Django 系统检查框架,即验证 Django 项目的一系列静态检查。如果一切正常,你将看到这 个消息:

System check identified no issues (0 silenced)。

如若不然,请确保你输入的模型代码是正确 的。错误消息应该会告诉你代码哪里出错了。只要觉得模型有问题,就可以运行 python manage.py check, 它能捕获全部常见的模型问题。

确认模型有效之后,运行下述命令,告诉 Django 你对模型做了修改(这里是新建了模型): python manage.py makemigrations classManage

一切顺利的话,应该看到下面的输出:

C:\coding\Django\newweb>python manage.py makemigrations classManage
Migrations for 'classManage':
  classManage\migrations\0001_initial.py
    - Create model Student

C:\coding\Django\newweb>

Django 把对模型(也就是数据库模式)的改动存储在迁移中,迁移就是磁盘中的文件。运行上述命令后, books 应用的 migrations 文件夹里会出现一个名为 0001_initial.py 的文件。

migrate 命令会查看最新的迁移 文件,自动更新数据库模式;不过,我们先来看看将运行的 SQL。sqlmigrate 命令的参数是迁移名称,输出 的结果是对应的 SQL:

python manage.py sqlmigrate classmanage 0001

正常的话可以看到下面的输出:

C:\coding\Django\newweb>python manage.py sqlmigrate classManage 0001
--
-- Create model Student
--
CREATE TABLE `classManage_student` (`id` integer NOT NULL PRIMARY KEY, `name` varchar(20) NOT NULL, `age` integer NOT NULL, `sex` varchar(10) NOT NULL, `score` varchar(100) NOT NULL, `skill` integer NOT NULL);

C:\coding\Django\newweb>

这其实就是Django打算执行的sql语句,sqlmigrate 命令并不创建表,其实它根本不接触数据库,而是在屏幕上输出 Django 将执行的 SQL。如果愿意,可以把输出的 SQL 复制粘贴到数据库客户端里,然而,Django 为提交 SQL 提供了更为简单的方式 ——migrate 命令:

python manage.py migrate

执行之后看到如下结果:

C:\coding\Django\newweb>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, classManage, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying classManage.0001_initial... OK
  Applying sessions.0001_initial... OK

C:\coding\Django\newweb>

那些额外的输出是首次运行迁移时 Django 创建的系统表,是 Django 内置应用所需的。迁移是 Django 把模型改动(添加字段、删除模型,等等)应用到数据库模式的方式。

5、数据操作

我们先在urls.py文件中创建4个path函数,用于数据的增、查、改、删操作,

from django.contrib import admin
from django.urls import path
from newweb.views import *
from classManage.views import *

urlpatterns = [
    path('',now),
    path('admin/', admin.site.urls),
    path('hello/',hello),
    path('student/<int:id>/',student),
    path('student/<str:sex>/',student2),
    path('notice',classnotice),
    path('add/',addstudent),
    path('find/',findstudent),
    path('modify/',modifystudent),
    path('del/',delstudent),
]

注意这里要加一句引入

from classManage.views import *

这样才能把新创建的app里面的视图函数导入。

然后在  views.py文件对应地创建四个视图函数,和上面的四个path函数对应起来。

#添加记录
def addstudent(request):  
    s1=Student(id=1,name='郭靖',age=19,sex='male',score=98)
    s1.save()
    s2=Student(id=2,name='黄蓉',age=17,sex='female',score=86)
    s2.save()
    return HttpResponse('{}和{}同学已经添加成功'.format(s1.name,s2.name))


#查询记录
def findstudent(request):  
    s = Student.objects.get(name='郭靖')
    return HttpResponse('你要查询的{}同学信息如下:姓名:{},年龄{},性别{},成绩{},武力值{}'.format(s.name,s.name,s.age,s.sex,s.score,s.skill))

#修改记录
def modifystudent(request):  
    s = Student.objects.get(name='郭靖')
    s.score = 100
    s.save()
    return HttpResponse('{}同学的{}已经修改成功'.format(s.name,s.score))

#删除记录
def delstudent(request):  
    s = Student.objects.get(name='郭靖')
    name=s.name
    s.delete()
    return HttpResponse('{}同学已经删除成功'.format(name))

5.1添加数据

#添加记录
def addstudent(request):  
    s1=Student(id=1,name='郭靖',age=19,sex='male',score=98)
    s1.save()
    s2=Student(id=2,name='黄蓉',age=17,sex='female',score=86)
    s2.save()
    return HttpResponse('{}和{}同学已经添加成功'.format(s1.name,s2.name))

考察上面这段代码,添加数据首先要实例化Student这个模型类,s1 和 s2就是实例

在实例化的同时,把各项参数赋予s1 和 s2,没有赋值的属性用默认属性(比如skill默认为100)

最后不要忘了用save()保存 

如果想一步完成创建和保存,也可以用下面的objects.create方法:

s3=Student.objects.create(id=3,name='王语嫣',age=16,sex='female',score=99)

效果和上面是一样的。

我们访问一下 http://127.0.0.1:8000/add/

5.2查询数据

5.2.1查询单条数据

# 实例=模型.objects.get(属性=值)
s = Student.objects.get(name='郭靖')

这里的属性就是数据表中的各个字段,也就是模型的各个属性

我们访问一下 http://127.0.0.1:8000/find/

5.2.2查询全部数据

 我们重新写一个视图函数 findall

def findall(request):
    students=Student.objects.all()
    info=''
    for s in students:
        info+='姓名:{},年龄{},性别{},成绩{},武力值{}'.format(s.name,s.name,s.age,s.sex,s.score,s.skill)+'<br>'
        
    return HttpResponse(info)

这里 objects.all() 就是获取全部student中数据的方法,注意这里得到的students是一个集合,所以后面用for循环把每个记录的数据读取到info中,最后输出展示 

然后在urls.py里面加一个path函数

urlpatterns = [
    path('',now),
    path('admin/', admin.site.urls),
    path('hello/',hello),
    path('student/<int:id>/',student),
    path('student/<str:sex>/',student2),
    path('notice',classnotice),
    path('add/',addstudent),
    path('find/',findstudent),
    path('findall',findall),
    path('modify/',modifystudent),
    path('del/',delstudent),
]

我们访问一下 http://127.0.0.1:8000/findall/

 

5.2.3根据条件查询数据

这里我们补充点知识,上一篇讲动态url的时候说过,URL里面可以传数字、字符串等各种值给视图函数作为参数,那么可不可以传多个参数呢?可以的,按照顺序以/分割开就行了,比如:

http://127.0.0.1:8000/find/id/3

这样就是传了 id 和 3两个参数给 find函数,只要在find函数里面设置相应的参数就可以接收到这两个值。我们用这个方法来设置条件查询。

在views.py中写一个视图函数 find_tj

def find_tj(request,tj,zhi):
    tj_dict={
        tj:zhi
    }
    students = Student.objects.filter(**tj_dict)
    info=''
    for s in students:
        info+='姓名:{},年龄{},性别{},成绩{},武力值{}'.format(s.name,s.name,s.age,s.sex,s.score,s.skill)+'<br>'
    return HttpResponse(info)

filter()函数的格式应该是

#实例=模型.objects.filter(属性=值)
students = Student.objects.filter(name='郭靖')

多个条件并列的情况,可以用逗号隔开,如

students = Student.objects.filter(条件1,条件2,。。。)

如果是多个条件 or 的情况,则要引入Q函数

from django.db.models import Q

students = Student.objects.filter(Q(条件1)|Q(条件2))

注意这里获得的实例students仍然是一个列表,即使只有一个值也是列表,没有值就是空列表。

因为我们输入的属性和值都不确定,所以filter支持输入字典的方式

我们把获取到的参数 tj 和 zhi 放到字典  tj_dict中,再把这个字典作为参数给filter()函数,这样就可以按照我们的条件来实现查询了。

当然urls.py中也要相应地加一个path函数

from django.contrib import admin
from django.urls import path
from newweb.views import *
from classManage.views import *

urlpatterns = [
    path('',now),
    path('admin/', admin.site.urls),
    path('hello/',hello),
    path('student/<int:id>/',student),
    path('student/<str:sex>/',student2),
    path('notice',classnotice),
    path('add/',addstudent),
    path('find/',findstudent),
    path('findall/',findall),
    path('findtj/<str:tj>/<str:zhi>',find_tj),   #把属性和值按顺序传给find_tj函数
    path('modify/',modifystudent),
    path('del/',delstudent),
]

我们来试试看,访问 http://127.0.0.1:8000/findtj/sex/female

看到了所有的女同学

再来试试看用名字直接访问  http://127.0.0.1:8000/findtj/name/郭靖

        当然,用URL进行前后端交互不是个好办法,等到后面我们学了表单之后,这个工作应该交给表单来完成。

5.3 修改数据

修改数据实际上先要执行查询,找到数据,然后用下面的方法修改

实例=模型.objects.get(属性=值)
实例.属性=新的值
实例.save()

s = Student.objects.get(name='郭靖')
s.score=100
s.save()

我们把郭靖的成绩改为了100分,我们访问http://127.0.0.1:8000/modify/

5.4 删除记录

很简单,就是直接实例化找到记录后,delete()

#删除记录
def delstudent(request):  
    s = Student.objects.get(name='郭靖')
    name=s.name
    s.delete()
    return HttpResponse('{}同学已经删除成功'.format(name))

要注意删除以后这条记录就没了,所以s.name不能再用,如果想要这个值,得提前把它存起来。

5.5 常用objects方法

5.5.1 get()

单条获取,结果为单条记录,格式

实例=模型.objects.get(属性=值)
#例:s = Student.objects.get(name='郭靖')

 5.5.2 filter()

过滤条件,结果为一个列表,格式:

实例=模型.objects.filter(属性=值)
#例:students = Student.objects.filter(name='郭靖')

5.5.3 exclude()

排除条件,结果为一个列表,格式:

实例 = 模型.objects.exclude(属性=值) 
#例:s=Student.objects.filter(sex="female").exclude(name='黄蓉')

5.5.4 .all()

全部选择,结果为一个列表

5.5.5 delete()

删除结果

5.5.6 aggregate()

聚合函数    AVG,SUM,MAX,MIN,COUNT
                    平均,和,最大值,最小值,数量
使用前需要导入相应模块,参数是带引号的字段名,格式:
 

from django.db.models import Avg,Min,Max,Sum,Count

。。。
。。。

students = Student.objects.aggregate(Avg('age'))

返回的是一个结果字典。{age__avg:17.75}

5.5.7 values()

这个返回的对象直接是一个字典结果集,不是模型对象结果集。格式:

实例 = 模型.objects.values()
例:students = Student.objects.filter(sex="female").values()

5.5.8 extra()

另外一种原生形式的查询,将sql的关键字 当做参数用,这是后续补充,代码执行填在整个文档最下方。

5.5.9 操作内参数

字段[__运算符] = 临界值,[]为可选运算符,没有就是等于,[]在用的时候不写。

gt lt gte lte
大于 小于 大于等于 小于等于
greater than less then greater than equal less than equal
startswith endswith istartswith iendswith
以什么字符开始 以什么字符结束 忽略 大小写的以什么 字符开始 忽略大小写的以什么字符结束
contains icontains exact iexact
包含什么字符 忽略大小写的包含 精确等于 忽略大小写的精确等于
year month day hour minute second

猜你喜欢

转载自blog.csdn.net/qq_41597915/article/details/126314161
今日推荐