笔者在上篇文章Django框架的初使用已对Django框架的前世今生、基本逻辑以及使用的基本框架搭建(搭建虚拟环境/创建Django项目/创建Django项目下的应用/运行服务器)进行了阐述,本文将从M模版、V视图、T模版依次论述,进一步梳理Django框架使用操作的逻辑流程,期望可以在加深本人理解的同时给他人带来一点帮助。
下面依次对模型M、视图V以及模版T进行逻辑梳理:
问1:
我们之前操作数据库是通过写sql语句,那么在使用Django能不能不写sql语句就可以操作数据库呢?
答1:
可以,就是通过接下来要给大家讲的ORM框架
。
django中内嵌了ORM框架,不需要直接面向数据库编程,而是定义模型类,通过模型类和对象完成数据表的增删改查操作。
使用django进行数据库开发的步骤如下:
- 在models.py中定义模型类
- 迁移
- 通过类和对象完成数据增删改查操作
下面我们以实际案例为例来给大家介绍Django中进行数据库开发的整个流程。
在应用下的models.py
进行模型类的定义,本实际案例将定义两个类分别是:
注意:在这里测试项目类假定是一类,测试人员类是多类,即测试项目-测试人员关系为一对多。
1)设计测试项目类
测试项目类:
类名:TestProjectInfo
测试项目名称:Tname
测试项目发布日期:Tdate
根据设计,在models.py
中定义测试项目模型类如下:
from django.db import models
class TestProjectInfo(models.Model):
Tname = models.CharField(max_length=20)
Tdate = models.DateField()
2)设计测试人员类
测试人员类:
类名:TestPeopleInfo
人员姓名:Pname
人员性别:Pgender
人员简介:Pcomment
人员所属项目:Pbook
打开models.py
,定义测试人员类代码如下:
class TestPeopleInfo(models.Model):
Pname = models.CharField(max_length=20)
Pgender = models.BooleanField()
Pcomment = models.CharField(max_length=100)
Pbook = models.ForeignKey('TestProjectInfo') # 外键设置,这句代码就让TestProjectInfo类和TestPeopleInfo类之间建立了一对多的关系。
迁移是指根据上述的模型类生成相对应的数据表。
迁移分为两个主要步骤:
- 生成迁移文件:根据模型类生成创建表的迁移文件。
- 执行迁移:根据第一步生成的迁移文件在数据库中创建表。
1)生成迁移文件
生成迁移文件命令如下:
python manage.py makemigrations
执行生成迁移文件命令后,会在应用test_app目录下的migrations目录中生成迁移文件:
在完成迁移文件的生成后,接下来我们就进行执行迁移的操作,该步骤操作就是将上述生成的迁移文件转化为数据库中对应的数据表,即会读取迁移文件自动帮我们在数据库中生成对应的表格。
2)执行迁移
执行迁移命令如下:m
python manage.py migrate
当执行迁移命令后,Django框架会读取迁移文件自动帮我们在数据库中生成对应的表格。
3)sqlite3数据库
在执行迁移后,我们会在test1
目录下看到db.sqlite3
文件,这就是项目对应的数据库,下面我们对sqlite3数据库进行介绍:
Django默认采用sqlite3数据库,上图中的db.sqlite3就是Django框架帮我们自动生成的数据库文件。 sqlite3是一个很小的数据库,通常用在手机中,它跟mysql一样,我们也可以通过sql语句来操作它。
sudo apt-get install sqlite3 //第一步为安装数据库
sudo apt-get install sqlitebrowser //第二步,安装sqlitebrowser图形界面
在django中对数据操作可以有两种方式:
- 第一种方式:可以通过进入项目的shell,进行简单的API操作;
- 第二种方式:django给用户提供了关于数据操作的后台管理图形界面,这一方法极大提高了生产效率;
一般对数据库的操作就是增删改查,在此部分笔者通过对测试项目表以及测试人员表的相关操作对shell的一些基础操作进行说明。
1)进入项目shell
的命令:
python manage.py shell
2)引入test_app/models
中的类:
from test_app.models import TestProjectInfo,TestPeopleInfo
3)查询相关数据表中的数据:
TestProjectInfo.objects.all()
TestPeopleInfo.objects.all()
t=TestProjectInfo() # t为新建的测试项目对象
t.Tname="测试项目1" # 为对象t的Tname属性赋项目名“测试项目1”
from datetime import date # 从datetime模块中导入date时间函数
t.Tdate=date(2020,1,29) # 为对象t的Tdate属性赋时间“2020年1月29日”
t.save() # 保存以上对象的相关数据
# 注意:在实际操作中需要把包括#以及后方的相关内容删除,它们只是起解释备注的作用
t1=TestProjectInfo.objects.get(id=1) # t1为新建的测试项目id为1对应的测试项目
p=TestPeopleInfo()
p.Pname='纳米执笔'
p.Pgender=False
p.Pcomment='纳米视角公众号主理人'
p.Pbook=t1 # 测试项目与测试人员是一对多的关系,设置外键
p.save()
t1=TestProjectInfo.objects.get(id=1) # t1为测试项目id为1对应的测试项目
t1 # 查看测试项目id为1对应的测试项目的所有信息
t1.id # 查看测试项目id为1对应的测试项目的id值
t1.Tname # 查看测试项目id为1对应的测试项目的Tname值
t1.Tdate # 查看测试项目id为1对应的测试项目的Tdate值
t1.Tdate = date(2019,1,1) # 将测试项目id为1对应的测试项目的Tdate值修改为2019年1月1日
t1.save() # 保存修改后的值
t1 # 查看测试项目id为1对应的测试项目修改后的所有信息
t1.delete()
t1.testpeopleinfo_set.all()
在这里我们可以发现在我们查询某对象的所有信息时往往返回的信息并不如我们所愿,这里需要我们自己去定义相关的管理页面,大致方法有两种:
第一种是在我们的应用下的models.py
中的各类下定义 def __str__(self):
函数,在该函数中写入相应需要返回的相关信息;
第二种是在admin.py
中自定义类,并继承自admin.ModelAdmin
类。
这两种方法都将在下面用管理站点去进行数据操作中详细介绍。
使用Django的管理模块,需要按照如下步骤操作:
- 管理界面本地化
- 创建管理员
- 注册模型类
- 自定义管理页面
1)管理界面本地化
本步骤主要是进行管理界面的汉字化,以及时区的中国画。打开test1/settings.py
文件,找到语言编码、时区的设置项,将内容改为如下:
LANGUAGE_CODE = 'zh-hans' #使用中国语言
TIME_ZONE = 'Asia/Shanghai' #django中没有北京时间,使用中国上海时间
python manage.py createsuperuser
python manage.py runserver
http://127.0.0.1:8000/admin
3)注册模型类
test_app/admin.py
文件,编写如下代码:from django.contrib import admin
from test_app.models import TestProjectInfo,TestPeopleInfo
admin.site.register(TestProjectInfo)
admin.site.register(TestPeopleInfo)
TestProjectInfo
和TestPeopleInfo
的管理了。4)自定义管理页面
在未自定义前,在列表页只显示出了TestPeopleInfo object
或是TestProjectInfo object
,这样查看起来非常不方便。 django提供了自定义管理页面的功能,以便自定义列表页中显示哪些值。
test_app/admin.py
文件,自定义类,继承自admin.ModelAdmin
类。class TestProjectInfoAdmin(admin.ModelAdmin):
list_display = ['id', 'Tname', 'Tdate']
admin.site.register(TestProjectInfo, TestProjectInfoAdmin)
from django.contrib import admin
from test_app.models import TestProjectInfo,TestPeopleInfo
# Register your models here.
class TestProjectInfoAdmin(admin.ModelAdmin):
list_display = ['id', 'Tname', 'Tdate']
class TestPeopleInfoAdmin(admin.ModelAdmin):
list_display = ['id', 'Pname','Pgender','Pcomment']
admin.site.register(TestProjectInfo, TestProjectInfoAdmin)
admin.site.register(TestPeopleInfo, TestPeopleInfoAdmin)
问1:
后台管理页面做好了,接下来就要做公共访问的页面了。当我们刚刚在浏览器中输入 http://127.0.0.1:8000/admin/
之后,浏览器显示出了后台管理的登录页面,那这个服务器是怎么给我们找到这个页面并返回呢?
答1:/admin/是我们想要请求的页面,服务器在收到这个请求之后,就一定对应着一个处理动作,这个处理动作就是帮我们产生页面内容并返回回来,这个过程是由视图来做的。
使用视图时需要进行两步操作:
URLconf
视图就是一个Python函数,被定义在views.py
中。
打开test_app/views.py
文件,定义视图index
如下:
from django.http import HttpResponse
def index(request): # 视图的必须有一个参数,一般叫request
return HttpResponse("index") # 视图必须返回HttpResponse对象,HttpResponse中的参数内容会显示在浏览器的页面上
url
配置的目的是建立url
和视图函数的对应关系。
查找视图的过程:请求者在浏览器地址栏中输入
url
,请求到网站后,获取url
信息,然后与编写好的URLconf
逐条匹配,如果匹配成功则调用对应的视图函数,如果所有的URLconf
都没有匹配成功,则返回404错误。
需要两步完成URLconf配置:
- 在应用中定义
URLconf
- 包含到项目的
URLconf
中
在test_app
应用下创建urls.py
文件,定义代码如下:
from django.conf.urls import url
from test_app import views
urlpatterns = [
url(r'^index$', views.index),
]
打开test1/urls.py
文件,为urlpatterns
列表增加项如下:
url(r'^', include('test_app.urls')),
视图和URLconf
都定义好了,接下来在浏览器地址栏中输入网址:
http://127.0.0.1:8000/index
问题1:
在django中如何向请求者返回一个漂亮的页面呢?
**答2:**解决问题的技术来了:模板。
在Django中,将前端的内容定义在模板中,然后再把模板交给视图调用,各种漂亮、炫酷的效果就出现了。
test_app
下的视图index
创建模板index.html
,在这里需要注意下,为了后期在大量文件中方便找到不同应用对应模版,我们会在test1
下的一级目录中创建文件夹templates
,并在该文件夹下根据不同的应用创建对应的模版文件夹,具体的目录结构如下图:test1/settings.py
文件,设置TEMPLATES
的DIRS
值:'DIRS': [os.path.join(BASE_DIR, 'templates')], # 设置相对路径,避免后期文件移动带来的绝对位置的变化
{{变量名}}
{%代码段%}
templtes/test_app/index.html
文件,定义代码如下:
测试项目列表
{{title}}
{%for i in list%}
{{i}}
{%endfor%}
调用模板分为三步骤:
打开test_app/views.py
文件,调用上面定义的模板文件
from django.http import HttpResponse
from django.template import loader,RequestContext
def index(request):
# 1.获取模板
template=loader.get_template('test_app/index.html')
# 2.定义上下文
context=RequestContext(request,{'title':'测试项目列表','list':range(10)})
# 3.渲染模板
return HttpResponse(template.render(context))