Python学习笔记 | 实例解析利用Django框架搭建Web应用
- 编程
- 2023-02-03
首先,Django是什么?Django是使用 Python 语言开发的一款免费开源的 Web 应用框架,用于搭建网站后端即服务器端应用和服务。
其次,什么是Web 应用框架?Web 框架是一组Web编程工具,可以帮助开发人员轻松构建动态网站、Web 应用程序和Web服务,它包含几个用于访问底层数据资源的应用程序编程接口 (API),以及允许你在浏览器中呈现信息的模板功能。
随着互联网的深度发展,Web开发从以前的混合式开发更新到现在的前后端分离式开发。前端主要关注用户界面和信息交互,后端接收并处理数据请求,然后将数据返回到前端。二者既相互独立又相互合作,django框架就是这样的工作方式。
一、Django框架介绍
(一)Django框架的特点
功能完整:Django 定义了服务发布、路由映射、模板编程、数据处理的一整套功能文档完善:Django 官方提供了完善的在线文档,为开发者提供技术支持集成 ORM 组件:Django 的 Model 层自带数据库 ORM 组件,为操作不同类型的数据库提供了统一的方式URL 映射技术:Django 使用正则表达式管理URL映射,因此给开发者带来了极高的灵活性安全可靠:Django 可以防范许多漏洞,包括SQL注入,跨站点脚本,跨站点请求伪造和点击劫持(二)Django框架的模式
Web框架通常有两种模式:MVC(模型/视图/控制器)和 MVT(模型/视图/模板),Django框架采用的是MVT模式。这两种模式的特点如下:
1、MVC模式
适合大型应用的开发,不适合小型应用不涉及URL映射流程定义清晰,易于理解M表示Model,模型,主要用于对数据库层的封装和交互V表示View,视图,用于向用户展示结果C表示Controller,控制器,用于处理请求、获取数据、返回结果2、MVT模式
适用于小型和大型应用发生 URL 模式映射与 MVC 相比,流程有时更难理解M表示Model,模型,主要用于对数据库层的封装和交互V表示View,视图,用于向用户展示结果T表示Template,模板,负责呈现内容到浏览器Django框架即MVT模式的运行流程如下图:
MVT模式流程图
【注】使用Django开发Web应用,将紧紧围绕上面的流程图展开,当思路不清时可以回头多看看这个流程示意图。
(三)Django模块的安装
Django跟其它第三方模块一样,使用之前要先进行安装。安装方法分两种:集成开发环境中安装和命令行方式安装,这里不再赘述。建议安装最高版本,目前为Django 4.1.5,低版本的Django服务遇到错误就会自行停止,不能够自动刷新重启。
二、Django项目的创建和运行
初学Django会感觉到它的逻辑关系非常复杂,配置和搭建过程很零散、琐碎,很多功能实现方法都是拆解成多个环节,不容易理解和掌握。但实际上Django这样做,是为了让搭建方式更加灵活,更好地控制整个Web框架。
(一)项目创建
创建Django项目有两种方式,一是在集成开发环境中创建,二是使用命令行方式创建。经过实际应用体验,感觉采用命令行方式创建Django项目更加方便灵活,因此下面将重点介绍这种方式。
1、在集成开发环境中创建Django项目
以Pycharm为例,点击菜单栏File→New Project...,在弹出的新建窗口左侧项目列表中选择Django,在窗口右侧配置Django项目的存放路径和项目名称,以及虚拟环境和Python解释器,点击创建按钮即可。
2、使用命令行方式创建Django项目
打开Windows系统的命令行终端,进入要存放Django项目的文件夹。如果使用的是虚拟环境,那么需要先激活虚拟环境,再进入这个虚拟环境项目的根目录。以我的电脑为例,使用虚拟环境的python项目目录为D:\mypython,新建的Django项目my_django就准备存放在这个目录中,命令行操作如下:Microsoft Windows [版本 10.0.22621.382] (c) Microsoft Corporation。保留所有权利。 C:\Users\Administrator.User-2022BIVGGU>d: D:\>cd mypython D:\MyPython>cd venv 进入虚拟环境目录 D:\MyPython\venv>cd Scripts D:\MyPython\venv\Scripts>activate 激活虚拟环境,Django模块就安装在这个虚拟环境中 (venv) D:\MyPython\venv\Scripts>cd .. 回退到虚拟环境项目的根目录 (venv) D:\MyPython\venv>cd .. (venv) D:\MyPython>输入创建Django项目的命令并回车,将在当前文件夹下创建指定的文件夹,即Django项目。如果事先没有激活虚拟环境,那么这里将提示没有这个外部命令,使用公共环境不涉及此问题。创建Django项目的命令如下(命令行最后的参数my_django是项目名称):django-admin startproject my_django这样就创建了一个名称为my_django的Django项目,文件信息如下图:
Django项目文件夹
(二)项目运行
1、启动Django服务
Django项目运行,指的就是启动Django开发服务,让Django为我们搭建一个Web运行环境,这样就可以使用浏览器访问Django项目了。运行Django服务的命令行如下:
(venv) D:\MyPython>cd my_django 进入Django项目目录 (venv) D:\MyPython\my_django>python manage.py runserver 执行启动服务命令 以下为系统显示信息 Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions. Run python manage.py migrate to apply them. January 29, 2023 - 17:13:36 Django version 4.1.5, using settings my_django.settings Starting development server at http://127.0.0.1:8000/ Quit the server with CTRL-BREAK.
【命令解析】首先,需要进入新建的Django项目目录,目录中包含一个manage.py管理文件,启动Django服务正是通过Python加载这个管理文件实现的。其次,通过系统提示信息我们可以看到,Django为我们开启了本地访问服务,默认端口号是8000,如果自己想设置端口号,那么在启动服务命令后面加上指定的端口号就可以了,如python manage.py runserver 8080。
2、访问Django欢迎页面
在浏览器地址栏中输入127.0.0.1:8000并回车,如果以上操作都没有问题,那么浏览器中将显示Django的欢迎页面,说明Django项目创建成功,Django服务开启成功。如下图:
Django欢迎页
在后面介绍的配置文件settings.py中,将语言码修改为zh-hans,时区修改为Asia/Shanghai,欢迎页面将变成中文显示。如下图:
Django中文欢迎页
三、Django主项目文件介绍
通过上面的一系列操作,Django主项目已经创建完毕,其文件结构如下:
my_django 项目文件夹 │ ├── my_django 主项目配置文件夹 │ ├── __init__.py │ ├── asgi.py │ ├── settings.py 配置文件 │ ├── urls.py url路由配置文件 │ └── wsgi.py │ ├── db.sqlite3 sqlite3数据库文件 └── manage.py 管理文件
通过上面的项目文件结构可以看到,项目主文件夹下包含两个文件:db.sqlite3和manage.py。其中,db.sqlite3是Django默认配置了SQLite3数据库而自动生成的数据库文件,manage.py是Django框架的管理文件,用于开启Django服务、创建应用程序等。
另外,项目文件夹中还包含一个跟项目文件夹同名的子文件夹,这个子文件夹里面包含了两个最重要的配置文件:settings.py和urls.py,下面将主要介绍这两个文件。
(一)配置文件settings.py
settings.py至关重要,Django框架的所有全局配置都在这个文件中,下面在代码中进行详细介绍。
from pathlib import Path # 创建项目的基础路径,当前文件(settings.py)绝对路径的父目录的父目录,也就是项目的根路径 BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ # Django自动生成的密钥 SECRET_KEY = django-insecure-)#-(j9ww6av4ff-t%iie(9n9#b4*sx+ow6i%*!sv#b+pzp36eo # 调试模式为真,用于开发调试,外界不能访问;当项目正式应用时,要把调试模式设置为假 DEBUG = True # 允许访问的主机,可以在列表中添加允许访问的主机IP地址,通常设置为[*],表示允许全部访问 ALLOWED_HOSTS = [] # 应用程序定义,创建的应用程序一定要在这里进行定义, # 否则应用程序的模型和视图文件不能被加载,自己编写的所有函数都不能执行 # 例如我们创建了一个博客应用,应用程序名称为blog,那么就可以在下面添加定义 INSTALLED_APPS = [ django.contrib.admin, # 网站管理 django.contrib.auth, # 认证管理 django.contrib.contenttypes, # 内容类型管理 django.contrib.sessions, # 会话管理 django.contrib.messages, # 消息管理 django.contrib.staticfiles, # 静态文件管理 blog.apps.MyappConfig, # 这是我们自己添加的博客应用定义,可以简写成blog ] # 定义中间件,用来拦截和检查访问状态,例如在博客中采用了中间件,那么就可以在下面添加定义 middleware = [ django.middleware.security.SecurityMiddleware, django.contrib.sessions.middleware.SessionMiddleware, django.middleware.common.CommonMiddleware, django.middleware.csrf.CsrfViewMiddleware, django.contrib.auth.middleware.AuthenticationMiddleware, django.contrib.messages.middleware.MessageMiddleware, django.middleware.clickjacking.XFrameOptionsMiddleware, blog.AdminMiddleware.AdminLoginMiddleware, # 自定义中间件 ] # 定义url总出口为主项目配置文件夹(跟项目主文件夹同名的子文件夹)下的urls.py root_URLCONF = my_django.urls # 模板定义 TEMPLATES = [ { BACKEND: django.template.backends.django.DjangoTemplates, DIRS: [], # 在该列表中添加项目的模板文件夹路径信息,如:[os.path.join(BASE_DIR, templates)] APP_DIRS: True, OPTIONS: { context_processors: [ django.template.context_processors.debug, django.template.context_processors.request, django.contrib.auth.context_processors.auth, django.contrib.messages.context_processors.messages, ], }, }, ] WSGI_APPLICATION = my_django.wsgi.application # Database # https://docs.djangoproject.com/en/4.1/ref/settings/#databases # 数据库配置,默认配置的是sqlite3数据库,如果不使用默认的数据库文件,则在下面更改 DATABASES = { default: { ENGINE: django.db.backends.sqlite3, # 数据库引擎 NAME: BASE_DIR / db.sqlite3, # 可以将db.sqlite3更改为blog.db } } # MySQL数据库配置,需要加载mysqlclient模块中的 MySQLdb类,要事先安装 mysqlclient模块 # DATABASES = { # default: { # ENGINE: django.db.backends.mysql, # 数据库引擎 # NAME: mydb, # 数据库名 # USER: ROOT, # 用户名 # PASSWORD: , # 密码 # HOST: localhost, # 主机地址 # PORT: 3306, # 端口号 # } # } # Password validation # https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { NAME: django.contrib.auth.password_validation.UserAttributeSimilarityValidator, }, { NAME: django.contrib.auth.password_validation.MinimumLengthValidator, }, { NAME: django.contrib.auth.password_validation.CommonPasswordValidator, }, { NAME: django.contrib.auth.password_validation.NumericPasswordValidator, }, ] # Internationalization # https://docs.djangoproject.com/en/4.1/topics/i18n/ # 语言码和时区设置 LANGUAGE_CODE = en-us # 语言设置,中文是zh-hans TIME_ZONE = UTC # 时区设置,中国时区是Asia/Shanghai USE_I18N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.1/howto/static-files/ # 设置静态文件url地址 STATIC_URL = static/ # 可以绑定自己的静态文件目录 STATICFILES_DIRS = [ os.path.join(BASE_DIR, static), # static是存放静态文件的目录,即项目根目录下的static文件夹 ] # Default primary key field type # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = django.db.models.BigAutoField
(二)路由文件urls.py
1、urls.py文件的作用
路由文件urls.py是项目的url总出口,是由配置文件settings.py定义的,定义项为ROOT_URLCONF = my_django.urls,其中的my_django是主项目配置文件夹,urls就是指urls.py文件。
通过Web框架的MVT模式流程图可以看到,客户端请求首先发送到路由配置模块即urls.py文件,urls.py文件中定义了url地址和视图函数的对应关系,根据url地址匹配到视图中的对应函数名称,然后通知视图使用对应函数处理客户端请求。
2、urls.py文件的内容
from django.contrib import admin from django.urls import path from . import views # 导入应用程序的视图 urlpatterns = [ path(admin/, admin.site.urls), # 系统自动配置的后台管理应用,在后面介绍 # 以下例子是创建博客应用程序的添加、删除和显示功能的url映射 # 第一个参数是url地址,第二个参数是视图文件中的对应函数 ,第三个参数是对应的名称 path(add_blog/ , views.add_blog , name=add_blog), path(del_blog/ , views.del_blog , name=del_blog), path(show_blog/ , views.show_blog , name=show_blog), ]
3、urls.py文件的书写规范
现在介绍的urls.py文件,是主项目的路由配置文件,如果将整个项目的url路由都放在这里进行配置,那么势必会造成混乱。为此,我们采取子路由的形式来解决这个问题。
具体做法就是在每个应用程序中创建自己的子路由配置文件,例如在博客应用程序的文件夹中创建urls.py文件,然后在子路由文件中配置该应用程序的所有url路由,最后在主项目的urls.py文件中使用include方法将子路由文件包含进来,这样既实现了路由配置功能,又使得主项目路由配置文件保持简单干净、清晰明了,便于日后维护。
主项目urls.py文件的规范写法如下:
from django.contrib import admin from django.urls import path, include # 导入include urlpatterns = [ path(admin/, admin.site.urls), # 后台管理 path(blog/, include(blog.urls)), # 将博客的url子路由配置包含进来 ]
【注】子路由的url地址可以为空字符串,代表首页地址。
(三)数据库文件db.sqlite3
db.sqlite3是Django默认配置了SQLite3数据库而自动生成的数据库文件,在后面将介绍数据迁移操作,执行数据迁移命令后,系统就会根据模型文件models.py中的Model类的定义,自动在db.sqlite3这个数据库中创建相应的表。我们也可以使用其他方法创建SQLite3数据库,然后在主项目配置文件settings.py中修改数据库配置即可,这种情况下db.sqlite3就可以删除不用了。
四、应用程序的创建和配置
(一)创建应用程序
Django应用程序就是指Web项目的功能模块(网站栏目),例如博客、新闻、在线相册等,通常把一个功能模块单独创建一个应用程序。一个应用程序创建成功后,系统会自动生成应用程序的基本目录结构。创建应用程序的步骤与创建Django项目类似,使用命令行形式创建。步骤和代码如下:
打开windows系统命令行窗口,进入虚拟环境目录,激活虚拟环境,返回包含虚拟环境的Python项目根目录,进入Django项目目录,命令行内容如下:Microsoft Windows [版本 10.0.22621.382] (c) Microsoft Corporation。保留所有权利。 C:\Users\Administrator.User-2022BIVGGU>d: D:\>cd mypython D:\MyPython>cd venv D:\MyPython\venv>cd scripts D:\MyPython\venv\Scripts>activate (venv) D:\MyPython\venv\Scripts>cd .. (venv) D:\MyPython\venv>cd .. (venv) D:\MyPython>cd my_django (venv) D:\MyPython\my_django>在命令行窗口输入如下命令并回车,应用程序创建完毕(venv) D:\MyPython\my_django>python manage.py startapp blog使用Pycharm打开my_django这个Django项目,可以看到项目文件夹下新增了一个blog文件夹,即blog应用程序(二)注册应用程序
当一个应用程序创建完毕后,必须在主项目配置文件settings.py中注册应用程序,否则应用程序的模型和视图文件都无法加载。注册应用程序的代码如下:
INSTALLED_APPS = [ django.contrib.admin, # 网站管理 django.contrib.auth, # 认证管理 django.contrib.contenttypes, # 内容类型管理 django.contrib.sessions, # 会话管理 django.contrib.messages, # 消息管理 django.contrib.staticfiles, # 静态文件管理 blog.apps.MyappConfig, # 这是我们自己添加的博客应用定义,可以简写成blog ]
(三)在url主路由中配置应用程序
在介绍主项目路由配置文件urls.py时,为了使主项目路由文件简单干净、清晰明了,我们确定了一个主路由配置文件的规范写法,那就是每个应用程序各自创建自己的子路由文件,负责配置自己的所有url子路由,然后在主项目路由配置文件中使用include方法将各个应用程序的子路由文件包含进去,完成分级配置路由的功能。
因此,在应用程序创建完毕后,首先在应用程序子目录中手动创建一个urls.py文件,然后修改主项目url路由配置,代码如下:
from django.contrib import admin from django.urls import path, include # 导入include urlpatterns = [ path(admin/, admin.site.urls), path(blog, include(blog.urls)), # 将新建应用程序的url子路由配置文件包含进来 ]五、应用程序的文件介绍
手动创建urls.py文件之后,Django项目的总体文件结构如下:
my_django 项目文件夹 │ ├── blog 新建的blog应用程序文件夹 │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── models.py 模型文件 │ ├── tests.py │ ├── urls.py url子路由配置文件 │ └── views.py 视图文件 │ ├── my_django 主项目配置文件夹 │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py │ ├── db.sqlite3 sqlite3数据库文件 └── manage.py 管理文件
(一)模型文件models.py
1、模型文件介绍
Django框架是MVT模式,其中的M代表模型(Model),就是由 models.py 这个文件实现的,专门负责通过ORM方式与关系型数据库进行CURD(创建、更新、读取、删除)交互。
ORM,全称 Object Relational Mapping (对象关系映射),使用 ORM 我们可以通过类的方式去操作数据库,而不用再写原生的SQL语句,即把表映射成类、把行作为实例、把字段作为属性。这样,不管连接的是何种类型数据库,CURD的语句都是一样的,在更换不同类型的数据库时无须改动模型文件中的代码。实际上,ORM 在执行对象操作的时候,最终还是会把对应的操作转换为数据库原生语句,只是这些工作都不需要我们去做而已。
简而言之,模型文件models.py就是用来定义Model类,一个Model类对应一个数据库表,Model类的属性对应表的字段。如果表已经存在,那么设置的属性就会链接到表的相应字段;如果表不存在,则会根据Model类的属性设置创建一个新表。
注意事项:
模型类需要定义在 models.py 模块中模型类必须继承自 models.Model 类每一个类属性和数据库表中的一个字段一一对应2、在模型文件models.py中创建Model类
使用Pycharm打开Django项目,然后再打开新建的应用程序blog里面的models.py文件,编写Model类代码。models.py文件的示例代码如下:
from django.db import models from datetime import datetime # 导入日期时间模块 # 创建自己的Model类,必须继承models模块中的Model类, class Blog(models.Model): # 以下每个属性都对应blog表中的对应字段 id = models.AutoField(primary_key=True) # id,自动增加字段,不用修改该字段内容 title = models.CharField(max_length=255) # 标题,字符型字段,必须添加max_length参数 author = models.CharField(max_length=255) # 作者,同上 content = models.TextField() # 内容,长文本字段 add_time = models.DateTimeField(default=datetime.now) # 添加时间,日期时间型字段,默认值为当前日期时间 # 重写Model类的__str__方法,此方法在将对象转换成字符串时会被调用 def __str__(self): return f{self.id}:{self.title}:{self.author} # 定义新建或连接的表的名称,如果这里不定义表的名称,则自动命名为app名+_+Model类名 class Meta: db_table = blog
3、Model类的常见字段类型
AutoField:自动型字段,自动增加的数据库字段类型,例如id字段就可以使用该数据类型,参数中必须填入primary_key=TrueBigAutoField:和AutoField相同,只是比AutoField要大,参数中必须填入primary_key=TrueCharField:字符串型字段,必须设置max_length参数TextField:长文本型字段,用来存储文章内容等比较长的文本信息IntegerField:整型字段,主要用于存储整型的数据BigIntegerField:大整型字段,主要用于存储整型的数据SmallIntegerField:小整型,主要用于存储整型的数据FloatField:浮点型字段,存储浮点型数据BinaryField:二进制型字段,主要是存储原始的二进制数据BooleanField:布尔型字段,主要是存储布尔类型的数据,0和1DateField:日期型字段,日期格式为YYYY-MM-DDTimeField:时间型字段,时间格式为HH:MM:[ss[.uuuuuu]][TZ]DateTimeField:日期时间型字段,格式为YYYY-MM-DD HH:MM:[ss[.uuuuuu]][TZ],DateField、TimeField与DateTimeField有两个属性,配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库,配置auto_now=True,每次更新数据记录的时候都会更新该字段DecimalField:十进制型字段,主要存储固定精度的十进制数据,参数max_digits(小数总长度),decimal_places(小数位长度)EmailField:邮件型字段,存储电子邮件格式的数据FileField:文件型字段,存储上传的文件数据,参数upload_to="...."(上传文件的保存路径),storage=None(存储组件,默认django.core.files.storage.FileSystemStorage)FilePathField:文件路径型字段,存储文件路径的数据,提供遍历文件夹和文件的功能,参数path(文件夹路径),match=None(正则匹配),recursive=False(递归下面的文件夹),allow_files=True(允许文件),allow_folders=False(允许文件夹)ImageField:图像型字段,存储图片型数据,参数upload_to="....."(上传文件的保存路径),storage=None(存储组件,默认django.core.files.storage.FileSystemStorage),width_field=None(上传图片的宽度保存的数据库字段名<字符串>),height_field=None(上传图片的高度保存的数据库字段名<字符串>)GenericIPAddressField:通用IP地址型字段,存储IP地址信息数据NullBooleanField:可以存储布尔值数据,也可以存储空null数据PositiveIntegerField:主要存储正整数数据URLField:存储URL网址信息,Django Admin以及ModelForm中提供验证urlIPAddressField:Django Admin以及ModelForm中提供验证IPV4机制4、数据迁移
在主项目配置文件settings.py的INSTALLED_APPS项中,包含了Django自带的所有应用程序,我们自己创建的应用程序也需要在这里进行注册。在使用这些Django自带的应用程序和我们自己创建的应用程序之前,必须要在数据库中创建应用程序对应的数据表。为此,Django为我们提供了数据迁移命令,可以将这些应用程序中定义的数据结构迁移到数据库中。数据迁移步骤如下:
(1)生成迁移文件
生成迁移文件,是根据我们自己创建的Model类生成一个用于在数据库中创建数据表的py文件,即迁移文件。Django自带的应用程序不需要生成迁移文件这个步骤,因为Django已经为它们定义好了迁移文件。生成迁移文件命令如下:
(venv) D:\MyPython\my_django>python manage.py makemigrations Migrations for blog: blog\migrations\0001_initial.py - Create model Blog (venv) D:\MyPython\my_django>
通过命令执行信息可以看到,系统在blog\migrations文件夹中生成了一个0001_initial.py文件,这就是我们在模型文件models.py中创建的Blog类的数据迁移文件。
(2)执行迁移
准备好Model类的数据迁移文件后,就可以执行迁移命令了。执行迁移命令情况如下:
(venv) D:\MyPython\my_django>python manage.py migrate Operations to perform: Apply all migrations: admin, auth, blog, 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 blog.0001_initial... OK Applying sessions.0001_initial... OK (venv) D:\MyPython\my_django>
通过命令行窗口信息可以看到,相关应用程序的迁移文件都被成功执行,包括了我们上一步刚刚生成的Model类的迁移文件在内。在Pycharm集成开发环境中可以看到,Django项目根目录中的数据库文件db.sqlite3的图标,由空文档变成了数据库图标。在Windows系统资源管理器中可以看到,db.sqlite3文件的大小从0KB变成了132KB。通过SQLiteStudio软件添加db.sqlite3数据库后可以看到,名称为db的数据库中包含了很多迁移生成的数据表。其中,我们自己创建的Blog类中定义的blog表也已经存在,并且字段信息与Blog类中定义的相符。如下图:SQLiteStudio软件界面
至此,我们创建的my_django项目的数据库和相关数据表就已经生成和连接完毕,下一步就可以进行CURD操作了。关于CURD操作,我们在视图部分进行介绍。
(二)视图文件views.py和子路由配置文件urls.py
1、视图文件views.py
Django框架MVT模式中的V就代表视图View,用于接收、处理和返回数据,应用程序的所有功能都是在自己的视图文件views.py中实现的,每项功能对应一个函数。视图函数的格式如下:
def 函数名(request): 函数功能代码 …… return 响应方法
函数名会用在url子路由配置中,并与自己的url地址相关联,因此在命名时要具有代表性,并且简明扼要,便于理解和书写request参数是必须要有的,用来接收请求数据,参数名称随意,但是通常使用requestreturn语句必须要写,并根据实际需要编写后面的响应方法。例如,响应方法可以为HttpResponse(文本信息),直接向客户端浏览器返回提示用的文本信息。常用响应方法如下:HttpResponse(文本信息) # 直接返回响应信息 HttpResponse(status=403) # 返回403错误信息 HttpResponseNotFound(Page not Found) # 返回页面不存在时的提示信息 raise Http404(访问的页面不存在!) # 抛出404错误 JsonResponse({data: data}) # 响应json数据,参数的value值为json数据 redirect(reverse(url地址)) # 页面重定向到参数指定地址 render(request, html模板页面地址) # 将响应信息渲染到模板文件中,这是开发项目时最常用的方式【注】以上响应方法,在使用时需要从相应模块中导入
2、子路由配置文件urls.py
子路由配置文件与视图文件是相互关联的,因此要放在一起介绍。在视图文件中创建一个函数,就要在子路由配置文件中进行配置。每个子路由配置项包含三部分:url地址、视图函数和配置项名称,三者必须一一对应,这样才能够正确显示Web页面。其中url地址的书写方法非常灵活,除了正常url地址外,还允许使用路径转换器为视图函数传递参数,甚至可以使用正则表达式进行书写。示例代码如下:
from django.urls import path from . import views # 从同级目录中导入视图模块 urlpatterns = [ path(, views.index, name=index), path(example01/, views.example01, name=example01), path(example02//, views.example02, name=example02), path(example03//, views.example03, name=example03), path(example04///, views.example04, name=example04), path(example05///, views.example05, name=example05), path(example06////, views.example06, name=example06), re_path(r^example07/([0-9]{4})/([0-9]{2})/([0-9]{2})$,views.example07, name=example07), ]
路由配置的url地址中,使用尖括号<>括起来的形式,称为路径转换器,表示从请求的url地址中捕获一个值。常用的路径转换器如下:str:匹配除路径分隔符外的任何非空字符串 int:匹配0或者任意正整数 slug:匹配任意一个由字母或数字组成的字符串 uuid:匹配格式化后的UUID path:能够匹配完整的URL路径如果路由配置中使用了路由转换器,那么就需要在视图函数中定义相应的参数,用来接收路由转换器捕获的值。反过来说,当在编写视图函数时,除了request参数外还定义了其它参数,那么在配置url路由时就需要采用路由转换器的形式与参数进行匹配如果路由配置中使用了路由转换器,那么浏览器中的访问地址也要与之相匹配。例如:域名/example02/1001,域名/example04/1001/zhangsan ,域名/example05/2023/01等等如果路由配置中使用了正则,需要事先导入re_path模块3、Web功能实现的基本流程
在视图文件views.py中编写功能函数,接收处理数据后,返回响应信息在应用程序的url子路由文件urls.py中配置功能函数的url信息,包括url地址、对应的视图函数以及url名称,三者是互相关联的,在命名方面最好保持一致如果视图函数将反馈结果渲染到了模板上,那么就需要创建对应的html模板文件,并根据模板语法加载数据,最终呈现到客户端浏览器上4、不使用数据库的简单实例演示
本实例功能非常简单,不使用数据库和模板文件,但是很清晰地体现了视图函数和子路由配置的关系,这是Django框架的基本工作流程。
在视图文件views.py中创建视图函数,代码如下:from django.shortcuts import render, HttpResponse # 导入HttpResponse # Create your views here. # 创建博客首页视图函数,直接使用HttpResponse向客户端浏览器反馈文本信息 def index(request): # 参数request是必须有的,用来接收数据,可以随意命名,通常使用request return HttpResponse(我的第一个Django项目!) # 响应到客户端浏览器中在blog目录的urls.py文件中配置子路由信息,代码如下:from django.urls import path from . import views # 从当前位置导入视图模块 urlpatterns = [ # 第一个参数url地址为空字符串,表示首页 # 第二个参数views.index对应视图文件views.py中的index函数 # 第三个参数是该路由信息的名称,以后用来反推url地址 path(, views.index, name=index), ]开启Django服务,并访问127.0.0.1:8000/blog,效果如下图:【注】如果想通过127.0.0.1:8000直接访问这个页面,那么需要在主项目url路由配置文件中将blog应用程序的url地址设置为空字符串,表示首页。配置代码如下:
from django.contrib import admin from django.urls import path, include # 导入include urlpatterns = [ path(admin/, admin.site.urls), # 后台管理 path(, include(blog.urls)), # 将blog应用程序的url地址设置为空字符串 ]
5、数据库简单操作实例演示
本实例中的数据库操作均在后台执行,并未使用交互方式体现到Web页面上,只是为了演示数据库读写操作。
视图文件views.py的代码如下:from django.shortcuts import render, HttpResponse from .models import Blog # 这里必须导入模型中定义的Model类 # Create your views here. # blog首页视图函数 def index(request): return HttpResponse(我的第一个Django项目!) # 响应到客户端浏览器中 # 添加数据库信息视图函数 def add(request): ob = Blog() # 创建Model类的实例化对象 # 以下为各个字段赋值,其中id 和 add_time为自动添加,不需要赋值 ob.title = 我的第一篇博客 ob.author = python爱好者 ob.content = 这是我的第一篇博客,这个博客Web应用是采用Django框架搭建的! ob.save() # 保存数据 print(ob) # 自动调用Blog类的__str__方法,输出预设信息。此信息显示在Djando服务窗口中(Windows系统终端窗口) return HttpResponse(添加信息成功!) # 响应到客户端浏览器中 # 显示数据库信息视图函数 def show(request): ob = Blog.objects # 创建Model类的对象 data = ob.all() # 获取所有数据 return HttpResponse(data) # 响应到客户端浏览器子路由配置文件代码如下:from django.urls import path from . import views # 从当前位置导入视图模块 urlpatterns = [ path(, views.index, name=index), # 首页路由配置,url地址为空字符串代表首页 path(add/, views.add, name=add), # 新增信息路由配置 path(show/, views.show, name=show), # 显示信息路由配置 ]在浏览器上访问127.0.0.1:8000/blog/add/,浏览器中提示添加信息成功,并在Django的服务窗口中输出了一条信息:1:我的第一篇博客:python爱好者。这条信息显示的数据和格式就是我们在模型文件Model类的__str__方法中预设的在浏览器上127.0.0.1:8000/blog/show/,浏览器上显示信息:1:我的第一篇博客:python爱好者,说明数据库中已经存在一条记录。但是在show函数中我们采用了all()方法来获取所有数据,而返回的信息还是模型的__str__方法中预设的格式,说明__str__方法会影响数据库信息显示,最好在Model类中不定义__str__方法六、Django数据库基本操作(一)添加数据
以学生信息Model类为例:
方法一(常用方法)stu = Student() # 创建Model类实例化对象 stu.name = 小明 # 添加姓名信息 stu.sex = 男 # 添加性别信息 stu.age = 15 # 添加年龄信息 stu.save() # 保存方法二stu = Student(name=小明, sex = 男, age = 15) # 创建Model类实例化对象时直接添加信息 sut.save() # 保存方法三Student.objects.create(name=小明, sex = 男, age = 15) # 在Model类的对象管理器中创建信息(二)删除数据
model = Student.objects # 获取Model类的对象管理器 stu = model.get(id=12) # 在Model类的对象管理器中获取id等于12的学生信息实例 stu.delete() # 删除该实例
(三)修改数据
stu =Student.objects.get(id=10) # 直接获取id为10的学生信息实例 stu.name = 小红 # 修改姓名信息 stu.sex = 女 # 修改性别信息 stu.age = 14 # 修改年龄信息 stu.save() # 保存
(四)查询数据
1、过滤器
在Django数据库操作中,将返回查询集的方法称为过滤器。常用过滤器如下:
all():获取所有数据filter():根据过滤条件获取数据exclude():获取排除条件之外的所有数据order_by():按照指定字段升序排序values():一个对象构成一个字典,然后构成一个列表返回应用实例如下:
model = Student.objects sut_list = model.all() # 获取所有数据 sut_list = model.all()[5:10] # 获取所有数据中索引从5到9的数据 sut_list = model.filter(name=小红) # 获取姓名为小红的学生信息列表 sut_list = model.filter(name__contains=红) # 获取姓名中包含红的学生信息列表 sut_list = model.exclude(name__contains=红) # 获取名字中不包含红的学生信息列表 sut_list = model.exclude(name__startswith=张) # 获取不姓张的学生信息列表 sut_list = model.filter(age__gt=20) # 获取所有年龄大于20的信息 sut_list = model.filter(age__gte=20) # 获取所有年龄大于等于20的信息 sut_list = model.order_by(age) # 按照年龄升序排序
2、过滤器的方法
get():返回单个满足条件的对象count():返回当前查询的总条数first():返回第一个对象last():返回最后一个对象exists():判断查询集中是否有数据,如果有则返回True3、比较运算符
比较运算符用在过滤器的过滤条件中,在字段名后面加双下划线再加上比较运算符,即:字段名__比较运算符,用来实现SQL语句中where的功能。常用比较运算符如下:
contains:包含某文本startswith:以某文本开头endswith:以某文本结尾isnull:为空isnotnull:不为空in:在某列表范围里gt:大于gte:大于等于lt:小于lte:小于等于year、month、day、week_day、hour、minute、second:对日期类型的属性进行运算filter(filedate__year=1980) # 获取日期型字段filedate的年份为1980的数据 filter(filedate__gt=date(1980, 12, 31)) # 获取日期为(1980, 12, 31)的数据4、查询集的缓存
每个查询集都包含一个缓存,以加快查询速度。新建查询集的缓存为空,首次对查询集求值时,会发生数据库查询,django会将查询的结果放在查询集的缓存中,并返回请求的结果,接下来对查询集的所有操作都将重用缓存中的结果。因此,为了提高效率,我们必须尽可能重用缓存结果,来最小化对数据库的访问。下面举例说明:
情况一:以下代码构建了两个查询集,无法重用缓存,每次查询都会与数据库进行一次交互,增加了数据库的负载print([stu.name for stu in Student.objects.all()]) print([stu.name for stu in Student.objects.all()])情况二:以下代码创建了一个查询集,两次循环使用同一个查询集。第一次查询时将结果放进了缓存,第二次查询重用缓存中的数据querylist = Student.objects.all() print([stu.name for stu in querylist]) print([stu.name for stu in querylist])七、模板的使用一个完善的Web应用,都具有漂亮鲜明的页面效果,可以更好地完成动态交互功能,使浏览者赏心悦目。基于这种原因,我们就不能一直使用HttpResponse这种语句来简单反馈响应信息。作为优秀的Web框架,Django提供了模板功能,可以很便利地动态生成HTML模版页面。模板系统致力于表达外观,而不是程序逻辑。模板的设计实现了业务逻辑(view)与显示内容(template)的分离,一个视图可以使用任意一个模板,一个模板可以供多个视图使用。
(一)创建模板目录
模板需要有专门的目录,用来存放整个Django项目的HTML模板页面。创建步骤如下:
在Django项目目录下创建名称为templates的模板目录,模板目录名称可以改变,但是通常都使用templates在模板目录templates下,为每个应用程序创建子目录,应用程序的模板都保存在自己对应的模板子目录中,方便管理(二)配置模板目录
模板目录需要在主项目的settings.py配置文件中进行配置,否则系统将找不到模板文件。配置代码如下:
TEMPLATES = [ { BACKEND: django.template.backends.django.DjangoTemplates, DIRS: [os.path.join(BASE_DIR, templates)], # 模板目录配置 APP_DIRS: True, OPTIONS: { context_processors: [ django.template.context_processors.debug, django.template.context_processors.request, django.contrib.auth.context_processors.auth, django.contrib.messages.context_processors.messages, ], }, }, ]
(三)Django模板语言
为了实现模板封装和复用,提高HTML界面调试便捷性以及前后端解耦等目标,Django定义了自己的网络模板语言,称之为为DTL(Django模板语言)。
Django的模板系统不是简单的把Python嵌入到HTML中,它的设计宗旨是:模板系统旨在展示内容,而不是程序逻辑,因此不在HTML页面中嵌入Python。
简单的说,模板只负责渲染数据,大多数逻辑都交给视图(view)进行处理。
1、变量输出
在HTML模板文件中,使用两对大括号将变量括起来,这样就可以在浏览器上显示变量的值,此变量由视图函数在渲染方法中传入。注意,相邻的两个大括号之间不能有空格,大括号与变量名之间可以有空格。
格式:{{ 变量 }}
下面使用实例来演示模板文件的使用,以及在模板文件中使用变量。
创建视图函数打开blog目录中的views.py文件,添加如下代码:
# 添加信息视图函数 def add(request): ob = Blog() ob.title = 我的第二篇博客 ob.author = python爱好者 ob.content = 这篇博客是使用模板文件显示的,并且使用了Django模板语言的变量! ob.save() data_dict = {id: ob.id, title: ob.title, author: ob.author, conten: ob.content, add_time: ob.add_time} context = {data: data_dict} # 这个字典的key即data,就是传入模板文件的变量名 return render(request, blog/add.html, context) # 将数据渲染到模板文件add.html中
配置url路由打开blog目录中的urls.py文件,添加视图函数add的url配置,代码如下:
from django.urls import path from . import views # 从当前位置导入视图模块 urlpatterns = [ path(, views.index, name=index), # 首页路由配置,url地址为空字符串代表首页 path(add/, views.add, name=add), # 新增信息路由配置 path(show/, views.show, name=show), # 显示信息路由配置 ]
创建模板文件在项目目录下的templates模板目录的blog子目录中,创建添加信息模板文件add.html(使用Pycharm创建HTML文件,可以自动生成HTML的基础框架代码),然后进行简单设计,并将Django模板语言的变量添加的合适位置。代码如下:
我的博客应用 添加博客信息 序号:{{data.id}}
标题:{{data.title}}
作者:{{data.author}}
内容:{{data.content}}
添加时间:{{data.add_time}}
【注意】
模板文件中的变量名data,就是在视图函数add中传入render渲染方法的字典数据的key。变量名data后面的部分并不是数据表字段,而是字典的key,在Djando模板语言中不能使用中括号[]来取得字典的value值,必须使用点 . 的形式。当模版引擎遇到点(".")时,会按照下列顺序查询:字典查询→属性或方法查询→数字索引查询。如果变量不存在,模版系统将插入 (空字符串)。开启my_django项目的Django开发服务,并在浏览器中访问127.0.0.1:8000/blog/add,浏览器显示效果如下图:
添加信息界面
2、标签语句
Django模板语言中的标签,用来实现条件判断、循环、取得url地址等功能。
格式:{% 标签语句 %}
注意:大括号和百分号之间不能有空格,百分号和标签语句之间可以有空格。
(1)if 标签
if 标签用来实现条件判断功能,可以有elif和else语句,必须使用endif标签进行闭合。
格式如下:
{% if ... %} 逻辑1 {% elif ... %} 逻辑2 {% else %} 逻辑3 {% endif %}
(2)for 标签
for标签用来做循环控制,在HTML页面上循环生成数据,通常用于显示数据表格。
{% for ... in ... %} 循环逻辑 {% endfor %}
(3)url 标签
url标签用来反向解析url地址,即使用url路由配置中的name值来反推url地址,在模板文件中经常使用。
{% url name p1 p2 %} # p1和p2是可选参数
(4)csrf_token 标签
csrf_token是令牌标签,专门应用于Form表单页面,用于跨站请求伪造保护。这个标签不需要任何参数和其它语句,只要在Form表单代码的上面添加令牌标签即可。
{% csrf_token %}
(5)comment 标签
多行注释标签,这是Django模板语言的特有注释,在网页源代码中看不见,html的注释在网页上右键查看源代码能够看到。
{% comment %} 被注释信息 {% endcomment %} # 单行注释 {# 注释 #}
(6)include 标签
include是包含标签,用来加载模板并以标签内的参数渲染。
{% include "base/index.html" %}
下面再使用for标签来制作一个实例,利用表格来显示blog的所有数据。
创建视图函数打开blog目录中的views.py文件,添加如下代码:
# 显示信息视图函数 def show(request): ob = Blog.objects # 创建Model类的对象 data = ob.all() # 获取所有数据 return render(request, blog/show.html, {data: data}) # 将数据渲染到模版文件show.html中
配置url路由打开blog目录中的urls.py文件,添加视图函数show的url配置,代码如下:
from django.urls import path from . import views # 从当前位置导入视图模块 urlpatterns = [ path(, views.index, name=index), # 首页路由配置,url地址为空字符串代表首页 path(add/, views.add, name=add), # 新增信息路由配置 path(show/, views.show, name=show), # 显示信息路由配置 ]
创建模板文件在项目目录下的templates模板目录的blog子目录中,创建显示信息模板文件show.html,然后添加表格标签,在表头设置代码下面添加for便签,循环添加blog表中的记录信息。代码如下:
我的博客应用
博客信息列表 序号 标题 作者 内容 添加时间 {% for b in data %} {{b.id}} {{b.title}} {{b.author}} {{b.content}} {{b.add_time}} {% endfor %}
开启my_django项目的Django开发服务,并在浏览器中访问127.0.0.1:8000/blog/show,浏览器显示效果如下图:
显示信息界面
3、过滤器
在模板文件中,可以使用过滤器(filter)来改变变量在模板中的显示形式。Django的模板提供了许多内置过滤器,可以直接使用。过滤器看起来是这样的:{{ name | lower }},使用管道符号(|)来应用过滤器,符号(|)后面的lower就是过滤器,表示将前面的变量内容转成小写。
格式:{{ 变量|过滤器 }}
default{{ value|default:"nothing" }} # 为false或者空变量提供默认值lower{{ name|lower }} # 将变量name的值变为小写输出upper{{ name|upper }} # 将变量name的值变为大写输出length{{ value|length }} # 返回value值的长度,它对字符串和列表都起作用date{{ add_time| date:"Y-m-j" }} # 设置日期变量的显示格式time{{ value|time:"H:i" }} # 设置时间变量的显示格式dicsort{{ value|dicsort:"name" }} # 对字典变量按照指定值进行排序filesizeformat{{ value|filesizeformat }} # 对文件尺寸变量的值进行转换,如果value是123456789,输出将会是117.7MBget_digit{{ value|get_digit }} # 获取数字位数join{{ list| join:"," }} # 使用指定字符连接列表项可以在if标签中使用过滤器结合运算符{% if list1|length>1 %}(四)模板继承
模板继承是指创建一个父模板,按照Web应用的实际需求对父模板进行整体设计和美化,并在父模板的相应位置设置预留区域,其它所有模板都不必另行设计,而是直接继承父模板,变成父模板的子模板,子模板拥有与父模板一样的界面和元素,只需要根据自己的需要设计填充预留区域就可以了。
模板继承的好处是,只需要设计一个父模板,免去大量重复工作,并且所有页面风格统一。当需要更改Web页面时,只需要在父模板里更改即可,省时省力。
1、父模板定义
父模板的文件名通常设置为base.html,预留区域的代码如下:
{% block block_name %} 这里可以定义默认值 如果不定义默认值,则表示空字符串 {% endblock %}
【注意】预留区域在Django模板语言中称之为block块,每个块都有一个名字,不同的块的名字不能相同,否则Django服务就会报错,甚至服务自动停止。
2、子模板定义
在子模板文件最上方添加继承代码,如下:{% extends "base.html" %}在子模板中使用block填充预留区域{% block block_name %} 实际填充内容 {% endblock %}3、注意事项
在子模板中,extends标签必须是模板中的第一个标签不能在一个模板中定义多个相同名字的block标签在子模板中,不必填充全部的block块。未填充的block块,则使用父模板中的默认值如果发现在模板中存在大量的重复内容,那么就应该把重复内容移到父模板中为了更好的可读性,可以给endblock标签一个名字,例如endblock block_name4、模板继承实例
(1)父模板
HTML代码{% block title %}网页标题{% endblock %}
返回首页 | 发布照片 | 浏览相册
{% block bodytitle %}模版标题{% endblock %} {% block content %} 此处为预留文本区域 {% endblock %}
本相册系统为演示Django框架使用。 本相册使用静态文件方式管理图片。 相册保留在必要时删除与国家法律法规相抵触图片的权利。
显示效果父模板显示效果图
(2)子模板
HTML代码{% extends "album/base.html" %} {% block title %}在线相册V1.0{% endblock %} {% block bodytitle %}发布照片信息{% endblock %} {% block content %} {% csrf_token %} 标题:照片:
{% endblock %}
显示效果子模板显示效果图
八、静态文件
在设计HTML模板页面时,需要用到CSS、js和图片文件,这些都是静态文件。只把静态文件放置在文件夹中,前端浏览器是无法加载的,需要对静态文件进行配置。
创建和配置静态文件目录与模板目录基本相同,流程如下:
创建静态文件目录在主项目目录下新建名称为static的子目录,在static目录中创建所有应用程序的静态子目录,用来存放各自的静态文件。
配置静态文件在主项目配置文件settings.py中进行如下配置:
STATIC_URL = static/ # 访问静态文件的url地址 STATICFILES_DIRS = [ os.path.join(BASE_DIR, static), # 存放静态文件的目录 ]
【注意】静态文件的访问地址是127.0.0.1:8000/static/,静态文件目录是主项目下的目录。
引用静态文件在HTML模板中引用静态文件有两种方式:一是硬编码,就是直接引用静态文件的url地址;二是软编码,就是使用标签语句读取静态文件。使用软编码引用静态文件的好处是,当静态文件目录进行了更改,只需要在settings.py文件中更改配置即可,引用静态文件的模板文件内容不需要变动。缺点是经常调试不通,尤其是在使用了继承的子模板中更难调试,代码互相冲突。
使用标签语句读取静态文件的代码如下:
# 读入静态文件的标签语句,该语句尽量放在HTML文件的上部 # Django后期版本将该语句更改成了{% load static %} {% load static from staticfiles %} # 引用静态文件
访问静态文件的运行效果在静态文件目录static中新建一个blog子目录,在blog子目录中放置一张文件名为color.png的图片,在浏览器中访问127.0.0.1/static/blog/color.png,运行效果如下:
访问静态文件效果图
九、Web在线相册案例解析
本案例使用上面介绍的内容,实现了图片文件上传、图片缩放、对数据库进行增删改查操作等功能,并且使用分页显示模块为查询页面添加了分页显示功能。本案例规模虽小,但是却完整地演示了Django项目开发的全流程,可供日后备查和参考。
Web相册效果演示视频如下:
(一)创建项目
打开Windows系统的命令行窗口,进入d:\mypython\venv\scripts文件夹,运行activate命令激活虚拟环境。回退到d:\mypython,在命令行窗口输入新建Django项目命令。命令如下:
django-admin startproject my_album
(二)创建应用程序
在命令行窗口进入项目文件夹my_album,运行新建应用程序命令。命令如下:
python manage.py startapp album
(三)配置项目
在主项目配置文件settings.py中配置如下:
""" Django settings for my_album project. Generated by django-admin startproject using Django 4.1.5. For more information on this file, see https://docs.djangoproject.com/en/4.1/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/4.1/ref/settings/ """ import os.path from pathlib import Path # Build paths inside the project like this: BASE_DIR / subdir. BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = django-insecure-5ov&gerz-7efp9=tb*zm!$_fu(lky1_m0g4u+izcg($qjgdn-t # SECURITY WARNING: dont run with debug turned on in production! DEBUG = True # 调试模式开启状态 ALLOWED_HOSTS = [*] # 允许所有主机访问 # Application definition INSTALLED_APPS = [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, album, # 注册应用程序 ] MIDDLEWARE = [ django.middleware.security.SecurityMiddleware, django.contrib.sessions.middleware.SessionMiddleware, django.middleware.common.CommonMiddleware, django.middleware.csrf.CsrfViewMiddleware, django.contrib.auth.middleware.AuthenticationMiddleware, django.contrib.messages.middleware.MessageMiddleware, django.middleware.clickjacking.XFrameOptionsMiddleware, ] ROOT_URLCONF = my_album.urls # 项目url总出口 TEMPLATES = [ { BACKEND: django.template.backends.django.DjangoTemplates, DIRS: [os.path.join(BASE_DIR, templates)], # 配置模板文件目录 APP_DIRS: True, OPTIONS: { context_processors: [ django.template.context_processors.debug, django.template.context_processors.request, django.contrib.auth.context_processors.auth, django.contrib.messages.context_processors.messages, ], }, }, ] WSGI_APPLICATION = my_album.wsgi.application # Database # https://docs.djangoproject.com/en/4.1/ref/settings/#databases # 配置sqlite3数据库 DATABASES = { default: { ENGINE: django.db.backends.sqlite3, NAME: BASE_DIR / my_album.db, # 配置数据库文件 } } # Password validation # https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { NAME: django.contrib.auth.password_validation.UserAttributeSimilarityValidator, }, { NAME: django.contrib.auth.password_validation.MinimumLengthValidator, }, { NAME: django.contrib.auth.password_validation.CommonPasswordValidator, }, { NAME: django.contrib.auth.password_validation.NumericPasswordValidator, }, ] # Internationalization # https://docs.djangoproject.com/en/4.1/topics/i18n/ LANGUAGE_CODE = zh-hans # 配置语言为中文 TIME_ZONE = Asia/Shanghai # 配置时区为上海 USE_I18N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.1/howto/static-files/ STATIC_URL = static/ STATICFILES_DIRS = [ os.path.join(BASE_DIR, static), # 存放静态文件的目录 ] # Default primary key field type # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = django.db.models.BigAutoField
(四)配置url主路由
在主项目url路由配置文件urls.py中配置如下:
from django.contrib import admin from django.urls import path,include # 导入include方法 urlpatterns = [ # path(admin/, admin.site.urls), path(, include(album.urls)), # 包含子路由配置 ]
(五)创建相关目录
在主项目目录下创建模板目录templates,在templates目录下创建子目录album在主项目目录下创建静态目录static,在static目录下创建子目录css、images和photo。css子目录用来放置css文件,images用来放置模板文件需要加载的页面头部横幅图片、首页展示图片和菜单栏背景图片等,photo目录用来存放上传的图片及缩略图。(六)创建相关文件
1、静态图片文件
设计制作页面头部横幅图片、首页展示图片和菜单栏背景图片,并保存到相应静态文件目录中
2、css样式文件
编写css样式文件,保存到static/css目录的style.css文件中。内容如下:
@charset "utf-8"; /* CSS Document */ body { margin: 0px; padding: 0px; } #menu { background-image: url("../images/menuline.png"); background-repeat: repeat-x; background-position: left; height:30px; font-size: smaller; padding: 0px 20px; } #menu a { color:#FFFFFF; text-decoration:none; } #menu a:hover { color:#FF0000; text-decoration:underline; } #footer { background-image: url("../images/bottomline.png"); background-repeat: repeat-x; background-position: center; color:#FFFFFF; font-size: smaller; padding: 10px 20px; }
3、模板文件
在templates/album目录中创建base.html、index.html、add_photo.html、edit_photo.html、show_photo.html和view_photo.html,对父模板文件base.html进行设计,达到预期效果,其它均为子模板文件,继承base.html。
父模板文件base.html{% block title %}网页标题{% endblock %}
返回首页 | 发布照片 | 浏览相册
{% block bodytitle %}模版标题{% endblock %} {% block content %} 此处为预留文本区域 {% endblock %}
本相册系统为演示Django框架使用。 本相册使用静态文件方式管理图片。 相册保留在必要时删除与国家法律法规相抵触图片的权利。
首页模板文件index.html{% extends "album/base.html" %} {% block title %}在线相册V1.0{% endblock %} {% block bodytitle %}微云孤月,看花落的心碎,听岁月的无痕...{% endblock %} {% block content %} {% endblock %}添加照片模板文件add_photo.html{% extends "album/base.html" %} {% block title %}在线相册V1.0{% endblock %} {% block bodytitle %}发布照片信息{% endblock %} {% block content %} {% csrf_token %} 标题:照片:
{% endblock %}
编辑照片模板文件edit_photo.html{% extends "album/base.html" %} {% block title %}在线相册V1.0{% endblock %} {% block bodytitle %}修改照片信息{% endblock %} {% block content %} {% csrf_token %} 标题:{% endblock %}
查看照片模板文件view_photo.html{% extends "album/base.html" %} {% block title %}在线相册V1.0{% endblock %} {% block bodytitle %}发布照片信息{% endblock %} {% block content %}{{photo.title}}
{% endblock %}
显示所有照片信息模板文件show_photo.html{% extends "album/base.html" %} {% block title %}在线相册V1.0{% endblock %} {% block bodytitle %}浏览在线相册{% endblock %} {% block content %} 搜索关键字:
标题 图片 发表时间 操作 {% for photo in photo_list %} {{photo.title}} {{photo.addtime}} 编辑 删除 {% endfor %}
首页 上一页 {% for p in pagelist %} {% if p == pages %} {{p}} {% else %} {{p}} {% endif %} {% endfor %} 下一页 尾页{% endblock %}
(七)应用程序album中的相关文件
1、url子路由配置文件
在album目录中创建urls.py文件,用来配置应用程序album的所有url子路由。代码如下:
from django.urls import path from album import views urlpatterns = [ path(, views.index, name=index), path(add_photo/, views.add_photo, name=add_photo), path(add/, views.add, name=add), path(show_photo/, views.show_photo, name=show_photo), path(edit_photo/, views.edit_photo, name=edit_photo), path(view_photo/, views.view_photo, name=view_photo), path(update/, views.update, name=update), path(del_photo/, views.del_photo, name=del_photo), ]
2、模型文件
在album目录中的模型文件models.py中进行数据表配置。由于我使用SQLiteStudio工具创建的数据库和表,不需要在模型中创建,因此在这个模型文件中没有定义id和添加时间字段,这两个字段的内容都是自动添加的。模型文件models.py的代码如下:
from django.db import models from datetime import datetime # Create your models here. class Album(models.Model): title = models.CharField(max_length=255) image = models.CharField(max_length=255) addtime = models.DateTimeField(default=datetime.now) class Meta: db_table = album
3、视图文件
所有的功能函数都在视图文件views.py中,功能函数将响应数据渲染到相应的HTML模板文件上,url子路由文件中对视图中的函数和它的url访问地址进行映射,这就是url—视图函数—模板的关联关系。
视图文件views.py的代码如下:
import time from PIL import Image from django.shortcuts import render, redirect, reverse from django.http import HttpResponse from django.core.paginator import Paginator from .models import Album # Create your views here. def index(request): return render(request, album/index.html) # 添加照片页面函数 def add_photo(request): return render(request, album/add_photo.html) # 添加功能函数 def add(request): title = request.POST.get(title, None) file = request.FILES.get(photo, None) # 将时间戳转换成字符串,加上上传文件的文件名后缀,形成随机文件名 if title and file: filename = str(time.time()) + . + file.name.split(.).pop() with open(./static/photo/ + filename, wb+) as wfile: # 分块读取文件内容,并按块写入到目标文件 for chunk in file.chunks(): wfile.write(chunk) # 如果上传文件时图片,可以将上传的图片进行等比缩放,并重命名后保存 im = Image.open(./static/photo/ + filename) # 等比缩放,最长边为75像素 im.thumbnail((75, 75)) im.save(./static/photo/s_ + filename) # 将信息保存到数据库中 try: ob = Album() ob.title = title ob.image = s_ + filename ob.save() except: return HttpResponse(向数据库添加数据失败,请重新尝试!) return redirect(reverse(add_photo)) return HttpResponse(请输入标题并选择要上传的照片文件!) # 显示所有照片信息列表函数 def show_photo(request, page_num=1): try: # 判断搜索条件并封装数据 kw = request.GET.get(keyword) my_where = if kw is not None: data = Album.objects.filter(title__contains=kw) # contains是包含的意思,即模糊查询 my_where = ?keyword= + kw else: data = Album.objects.filter() # 使用过滤方法获取数据列表,不使用all方法 p = Paginator(data, 5) # 创建分页对象,5行数据为一页 if page_num < 1: page_num = 1 if page_num > p.num_pages: page_num = p.num_pages ulist = p.page(page_num) # 获取第几页数据列表 context = {photo_list: ulist, pages: page_num, pagelist: p.page_range, total_page: p.num_pages, mywhere: my_where} return render(request, album/show_photo.html, context) except: return HttpResponse(用户信息没有找到!) # 查看照片函数 def view_photo(request, uid=0): try: ob = Album.objects.get(id=uid) image_file = ob.image[2:] content = {photo: ob, image_file: image_file} return render(request, album/view_photo.html, content) except: return HttpResponse(发生未知错误,请重新尝试!) # 编辑页面函数 def edit_photo(request, uid=0): try: ob = Album.objects.get(id=uid) image_file = ob.image[2:] content = {photo: ob, image_file: image_file} return render(request, album/edit_photo.html, content) except: return HttpResponse(发生未知错误,请重新尝试!) # 更新编辑内容函数 def update(request): try: uid = request.POST[id] ob = Album.objects.get(id=uid) ob.title = request.POST[title] ob.save() return HttpResponse(修改成功!) except: return HttpResponse(修改失败!) # 删除信息函数 def del_photo(request, uid=0): try: ob = Album.objects.get(id=uid) ob.delete() return redirect(reverse(show_photo)) except: return HttpResponse(删除失败!)
【总结】Django框架项目,看起来内容很多,其实每项功能的代码都很少,只是结构比较分散。一项功能要涉及到url配置、编写视图函数和渲染模板,模板里还需要使用Django模板语言进行编写,过程跳转较多,这也是较难理解的地方。
如果仔细将总体流程捋顺清晰了,感觉Django项目开发还是相对挺容易的。最后,再一次将Django工作的整体流程跑一遍,加深一下理解!
客户端url请求→→主项目url路由解析→→应用程序url子路由解析→→视图文件中对应函数处理数据(通过模型操作数据库)→→将响应数据渲染到对应HTML模板文件→→生成最终HTML页面并返回到客户端浏览器