软件框架
定义
一个软件是由其中各个软件模块组成的,每一个模块都有特定的功能,模块与模块之间通过相互配合来完成软件的开发。
软件框架是针对某一类软件设计问题而产生的
Django遵循的是MVC思想
MVC框架
MVC的产生理念:分工,让专门的人去做专门的事情(比如:输入、处理、输出)
MVC的核心思想:解耦
MVC是三个模块的简称:
- M:model,模型,和数据库进行交互
- V:View,视图,产生html页面
- C:Controller,控制器,接收请求,进行处理,与M和V进行交互,返回应答
以通过浏览器注册用户信息为例:
Django简介
Django,发音为[`dʒæŋɡəʊ],是用python语言写的开源web开发框架,并遵循MVC设计。
MVT
Django是遵循MVC的一个Web框架,但是他有自己的一个名字,叫做MVT
快速开发
和DRY
原则。Do not repeat yourself。不要自己去重复一些工作
M:Model,模型,和数据库进行交互,与MVC中的M功能相同
V:View,视图,接收请求,进行处理,与M和T交互,返回应答,与MVC中的C功能相同
T:template,模板,产生html页面,和MVC终的V功能相同
MVT的各部分功能:
django官方网站:https://www.djangoproject.com/
虚拟环境
在Linux上,如果用pip3安装的包,会安装在/user/local/lib/python3.xx/dis-packages下面。当安装同一个包的不同版本的时候,后安装的版本会把原来安装的版本覆盖掉。
如何解决这个问题?
使用虚拟环境,所谓虚拟环境,就是真实python环境的一个复制版本。在虚拟环境中使用的python是复制的python,安装python包也是安装在复制的python中
ps:如果是在pycharm里的设置里面安装的,而不是用pip命令安装的,会默认安装在一个虚拟环境里面
Linux下安装虚拟环境的命令:
-
sudo pip install virtualenv 安装虚拟环境
-
sudo pip install virtualenvwrapper 安装虚拟环境扩展包
-
编辑家目录下面的.bashrc文件,添加如下两行内容
- export WORKON_HOME=$HOME/.virtualenvs
- source /user/local/bin/virtualenvwrapper.sh
-
使用source .bashrc使其生效
-
创建python2的虚拟环境:mkvirtualenv 虚拟环境名称
-
创建python3的虚拟环境:mkvirtualenv -p python3 虚拟环境名
-
进入虚拟环境工作:workon 虚拟环境名
-
查看机器上有多少个虚拟环境:workon 空格 + 两个tab键
-
退出虚拟环境:deactivate
-
删除虚拟环境:rmvirtualenv 虚拟环境名
在虚拟环境中的一些命令:
- pip list 查看安装了的包,pip freeze也可以
- pip install 包的名字(如果要指定版本号,再紧跟==版本号),如果使用sudo安装,仍然是安全到全局
Windows环境安装虚拟环境:
- pip list查看是否已经安装virtualenv
- 如果没有安装过:pip install virtualenv,安装成功后,会提示:Success fully installed virtualenv-xxx
- 在一个目录下创建虚拟环境:virtualenv 虚拟环境的名字
- 进入虚拟环境所在目录的scripts,查看scripts目录结构,可以看到激活虚拟环境的命令:activate.bat
- 执行activate命令
项目创建
django-admin startproject 项目名字(注意:需要先进入虚拟环境,Linux和Windows相同)
创建成功后,目录结构如下:
其中:
__init__.py
说明其所在路径是一个python的包- settings.py是项目的配置文件,比如项目要使用哪个数据库,就在里面配置
- urls.py url:在访问网站时,我们输入的网站就是一个url的地址。urls.py文件是进行url路由的配置(当我们输入一个地址后,他怎么给我们找到对应的处理函数是谁)
- wsgi.py Django是遵循wsgi协议的框架,wsgi.py就是web服务器和django交互的一个入口
- manage.py 是我们项目的管理文件,是一个可执行文件,通过该文件,我们可以管理整个项目
创建django应用
一个项目由很多个应用组成,每一个应用完成一个功能模块
创建应用的命令如下:python manage.py startapp 应用名
每创建一个应用,里面就会有如下文件:
其中:
__init__.py
说明该应用是一个python模块- models.py中写和数据库相关的内容
- views.py 接收请求,进行处理,与M和T进行交互,返回应答。定义处理函数(在django中称视图函数)
- tests.py写测试代码的文件,不怎么需要关心
- admin.py跟网站的后台管理相关的文件
- migrations文件夹:存放由模型类生成的迁移文件
在我们建立应用之后,必须建立应用和项目之间的联系,即:对应用进行注册:在settings.py中修改installed_apps配置项,eg:注册booktest应用
运行项目
运行一个web项目,就需要一个web服务器,而django本身给我们提供了一个web服务器,使用python manage.py runsevser运行该服务器,然后即可根据提示用浏览器访问
ORM
O:object,对象
R:relations,关系
M:mapping,映射
ORM的作用:建立类和表的对应关系
ORM让我们能够通过对类和对象的操作实现对表的操作,就不需要再去写sql语句。这是元类的一种最经典的应用
在创建的项目文件夹下的models.py文件中,我们设计和表对应的类,这个类被称做模型类
ORM的另一个作用:根据设计的类生成数据库中的表
模型(M)
模型类设计和表生成
模型类设计
在项目文件夹下的models.py文件中,比如我们定义一个图书类
from django.db import models
# Create your models here.
class BookInfo(models.Model):
# 必须继承了Model类之后,他才是一个模型类
# 模型类的名字就对应的表的名字为:应用名_小写的模型类名
# 模型类中的类属性就对应于表中的一个字段(列)
btitle = models.CharField(max_length=20) #书名
#通过models.CharField体现btitle的类型是一个字符串,max_length制定字符串的最大长度
bpub_date = models.DateField() #出版日期
#models.DateField说明其是一个日期类型
#在django中,id不需要我们定义,他会帮我们自动生成
模型类的字段属性和选项
模型类属性命名限制
- 不能是python关键字
- 不允许使用连续的下划线,不是由django的查询方式决定的
- 定义属性时需要指定字段类型,通过字段类型的参数指定选择,语法如下: 属性名 = models.字段类型(选项)
字段类型
使用时需要引入django.db.models包
-
AutoField 自动增长的IntegerField,通常不用指定,不指定时django会自动创建属性名为id的自动增长属性,在迁移文件中可以查看到
-
BooleanField 布尔字段,值为True或False
-
NullBooleanField 支持Null,True,False三种值
-
CharField(max_length=最大长度) 字符串,参数max_length指定最大字符个数,必须指定,不然报错
-
TextField 大文本字段,一般超过4k个字
-
IntegerField 整数
-
DecimalField(max_digits=None, decimal_places=None) 十进制浮点数,第一个参数表示总位,第二个参数表示小数位数
-
FloatField 浮点数,参数同上。注意:float的精确度比decimal小
-
DateField([auto_now=False, auto_now_add=False]) 日期,有两个可选参数:
- auto_now 表示每次保存对象时,自动设置该字段为当前时间,用于“最后一次修改”的时间戳,它总是使用当前日期,默认为false
- auto_now_add 表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认false
- 两个参数是相互排斥的,不能同时使用
-
TimeField 时间参数同DateField
-
DateTimeField 日期时间,参数同上
-
FileField 上传文件字段
-
ImageField 继承于FileField,对上传的内容进行校验,确保是有效的图片
选项
作为Field()中的参数
通过选项实现的字段的约束,选项如下:
- default 默认值。设置默认值
- primary_key 若为True,则该字段会成为模型的主键字段,默认值是false,一般作为AutoField的选项使用
- unique 唯一性约束,如果为True,这个字段在表中必须有唯一值,默认值是False
- db_index 若值为True,则在表中会为这个字段创建索引,默认值为False
- db_column 字段的名称,如果未指定,则使用属性的名称
- null 如果为True,表示允许为空,默认值是False
- blank 如果为True,则该字段允许为空白,默认值是False
更多的可以见官方文档
对比:null是数据库的概念,blank是后台管理页面表单验证范畴的
注意:当修改模型类之后,如果添加的选项不影响表的结构,则不需要重新做迁移,eg:blank和default
模型类生成表
一、 生成迁移文件
迁移文件是根据模型类生成的,生成的迁移文件存放在migrations文件夹下
命令:python manage.py makemigrations
二、执行迁移生成表
命令:python manage.py migrate
根据迁移文件生成表
注意:django默认使用的数据库是sqlite3,在项目文件夹下,与项目同名的文件夹下的settings.py文件中DATABASES字段处可以看到
当文件迁移后,我们就可以在项目文件夹下看到一个名为db.sqlite3的文件,即我们的数据库文件,可以直接使用相应软件打开
通过模型类操作数据表
- 使用python manage.py shell进入项目终端
- from booktest.models import BookInfo (from 应用名.models import 自己定义的类的名字)
- 创建类的对象:b = BookInfo()
- 增加实例属性(注意:这个实例属性的名字必须和类属性的名字一样):b.btitle = “天龙八部”
- from datetime import date
- b.bpub_date = date(1990,1,1)
- 然后就把这个实例属性里面保存的数据添加到数据库:b.save(),注意:这个方法是继承自models.Model
- 用 模型类名.objects查看对应表里面的数据(注意:是模型类名,而不是上面的变量名b),eg:查看id=1的记录:b2 = BookInfo.objects.get(id=1),b2是一个BookInfo类的对象。即:把查出来的数据是保存在一个对象里面,然后可以用类似:b2.btitle查看btitle对应的数据
- 更改数据:b2.bpub_date = date(1990,10,10),即:直接更改查询的对象的属性值即可,然后用b2.save()将保存同步到数据库
- 如何删除一条记录:b2.delete()
建立两张表之间的关系:外键
from django.db import models
# Create your models here.
class BookInfo(models.Model):
# 必须继承了Model类之后,他才是一个模型类
# 模型类中的类属性就对应于表中的一个字段(列)
btitle = models.CharField(max_length=20) #书名
#通过models.CharField体现btitle的类型是一个字符串,max_length制定字符串的最大长度
bpub_date = models.DateField() #出版日期
#models.DateField说明其是一个日期类型
#在django中,id不需要我们定义,他会帮我们自动生成
class HeroInfo(models.Model):
hname = models.CharField(max_length=20) #名字
hgender = models.BooleanField(default=False) #性别,布尔类型,default制定默认值
hcomment = models.CharField(max_length=128) #备注
# 在有一对多的关系的两个类中,需要在“多”的类中定义外键,建立“一”和“多”的关系
# 关系属性对应的表的字段名格式:关系属性名_id
hbook = models.ForeignKey('BookInfo',on_delete=models.CASCADE) # 建立了图书类和英雄人物类之间的关系,注意:如果两个类不在一个应用里面,则需要写成 应用.类名,eg:booktest.BookInfo
注意:往“多”类的属性里面赋值的时候,相关联属性其对应值必须是与其关联的类的对象,eg:
对该属性进行查看,发现其是一对象:
查看与“一”相关联的“多”的信息(eg:此处与图书相关联的英雄的信息)
注意:这里的heroinfo是小写
查询表中的所有内容:类名.objects.all(),返回的是一个列表,其中的元素为每一条数据的对象
后台管理
在所创建应用的对应文件夹下,有一个admin.py,(eg:本案例中为:/myProject/booktest/admin.py)通过它,我们实现后台的管理
步骤:
-
本地化
- 语言和时区的本地化:修改settings.py文件
- 语言和时区的本地化:修改settings.py文件
-
登录管理页面需要有一个管理员的账户:创建管理员:python manage.py createsuperuser
-
使用:python manage.py runserver启动服务器,然后就可以通过浏览器进行管理,127.0.0.1:8000/admin,然后就可以帮助我们管理数据库里面的数据。注意:服务器的默认端口是8000,但是我们也可以在运行时直接指定:python manage.py runserver 127.0.0.1:8001
-
注册模型类
在应用下的admin.py中注册模型类,告诉django框架根据注册的模型类来生成对应表管理页面
admin文件:
注册后的管理界面:
但是注意:表中的记录名为对应对象的字符串,如何使其显示我们能够看懂的内容?答:重写str方法,eg:
- 自定义管理页面:自定义模型管理类。模型管理类就是告诉django在生成的管理页面上显示哪些内容(比如,我们让其在浏览 器中显示图书名称的同时显示出版时间)
class BookInfoAdmin(admin.ModelAdmin):
# 自定义模型管理类,名字可以随便取,但是通常是:表的名字+Admin
list_display = ['id','btitle','bpub_date'] # 固定写法,列表中写要在页面中显示的内容
# 同时,在注册的时候,我们需要让该模型类知道自己的管理类是谁
admin.site.register(BookInfo, BookInfoAdmin) # 注意,该语句不能分两次写,否则会报错
视图(V)
在django中,通过浏览器去请求一个页面的时候,是使用视图函数来处理这个请求的,视图函数处理后,要给浏览器返回页面内容
视图函数的使用
一、定义视图函数
在应用下的views.py中,eg:定义一个名为index的视图函数(注意:视图函数必须有一个参数:request)
from django.http import HttpResponse
def index(request):
# 视图函数必须有一个request参数,它是一个HttpRequest对象
# 当用户输入http://127.0.0.1:8000/index的时候,要给浏览器返回一个内容
# 视图的作用,就是在里面会进行处理,如果要用到数据库,就与M交互,如果要产生页面,就与T交互
# 视图函数必须返回一个HttpResponse对象,需要从django.http中导入
# 所谓要产生页面就与T(template)进行交互:template就是一段html代码,当V拿到tempalte后,
# 将里面的部分数据用从M(数据库)拿来的数据进行替换,然后返回,浏览器就可以直接解析这段html代码从而在浏览器上显示对应内容
return HttpResponse("<h1>hello django!</h1>")
# 我们知道,一个地址对应一个处理函数,那么如何让django知道哪个地址是对应哪个处理函数?
# 答:进行url路由的配置
二、进行url的配置
首先我们要在应用对应的目录下建立urls.py文件,然后在其中创建一个列表,如下:
from django.conf.urls import url
from booktest import views
urlpatterns = [
# 通过url函数设置url路由的配置项
url(r'^index', views.index) #建立/index和视图index之间的关系
]
同时,我们也需要在项目的urls里面添加配置项
from django.contrib import admin
from django.urls import path,include
from django.conf.urls import url
urlpatterns = [
path('admin/', admin.site.urls), # 配置项
url(r'^', include('booktest.urls')) # 将booktest应用中的urls文件包含进来
# url函数第一个参数是一个正则表达式
]
效果图如下:
流程分析:
-
当我们在浏览器中输入127.0 .0.1:8000/index的时候,django拿到的是/index
-
然后就会拿这一部分去查找对应的视图
- 先到项目的urls文件里面去查找,拿该字符串与urlpatterns中每一项的第一个参数(正则表达式)进行匹配
- 如果匹配上了(由于我们在第二项只匹配了开头,那么无论匹配什么都能成功),就会执行后面的动作,于是django就拿着字符串到应用中去与应用中的urls进行匹配,但是注意:在整个匹配过程中,/index中,最前面的/不参与正则的匹配,匹配成功。(
在进行匹配时,会去掉匹配成功的部分,比如此处,我们在项目的urls中进行匹配时,由于只匹配了个开头,没有具体的数据,所以django还是拿着index去应用的urls中匹配,如果我们假设在项目的urls中匹配到了i,那么django就只会拿着ndex去应用中匹配
) - 然后一看对应的是一个视图,django就会去调用这个视图,然后获得返回的数据(
"<h1>hello django!</h1>"
) - 于是浏览器就可以进行显示
注意:在应用的urls文件中进行url匹配的时候,一定要严格匹配开头结尾,避免出现意外
模板(T)
django中的模板不仅仅是个html文件,还可以在其中定义变量,也可以写类似于编程语言的语句
模板文件的使用
-
创建模板文件夹(通常是在项目文件夹下创建templates)
-
配置模板目录(在项目的settings.py文件下),如下:
-
使用模板文件
- 加载模板文件:去模板目录下面获取html文件的内容,得到一个模板对象(通常,不同的应用会用到不同的模板文件,所以我们会再在templates下面建立与应用名同名的文件夹,用以存储该应用用到的模板文件)
- 定义模板上下文:向模板文件传递数据,即:如果模板中使用了变量,需要将变量的数据给他
- 模板渲染,读出变量后,将变量的位置替换掉,即得到一个标准的html文件
eg:
模板文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板文件</title>
</head>
<body>
<h1>这是一个模板文件</h1>
<p>我在这里使用了模板变量,在模板中使用变量,如果不是在代码段内,就要使用两个花括号括起来:{
{content}}</p>
<ul>模板中的代码段要写在两个%中间:{% for i in list %}
<li>{
{i}}</li>
{% endfor %}
<!-- 在模板中,如果使用代码,有开始就一定有结束,比如endfor,比如endif-->
</ul>
</body>
</html>
应用程序中的views文件
# -*- coding:utf-8 -*-
from django.shortcuts import render
# Create your views here.
from django.http import HttpResponse
from django.template import loader,RequestContext
def index(request):
# # 1. 加载模板文件
# temp = loader.get_template('booktest/index.html') #注意:这里的路径是相对与templates的
# # 返回值是一个模板对象
#
# # 2. 定义模板上下文:给模板文件传数据。所谓定义模板上下文,就是创建一个RequestContext对象
# context = RequestContext(request, {}) # RequestContext的第一个对象需要是一个request
# context.push(locals())
# # 要给模板文件传递的数据就放在第二个参数里面,其是一个字典,通过键-值对的方式传递
# # 由于我们这里没有用到变量,所以传空字典即可
#
# # 3. 模板渲染:产生标准的html内容
# # 模板对象temp里面有一个render方法,能够把RequestContext对象中对应的位置替换成对应的值
# # 然后返回替换后的内容:一个标准的html文件
# res_html = temp.render(request=request,context=locals())
# # 4. 返回给浏览器
#
# return HttpResponse(res_html)
return render(<