一、Django简介
第一个开放源代码的WEB应用框架,由python写成,初次发布于2005年7月,并于2008年9月发布了第一个正式版本1.0。主要有两种模式:MVC和MTV
MVC:
概述:一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进 和个性化定制界面及用户交互的同时,不需
要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理 和输出功能在一个逻辑的图形化用户界面的结构中
核心思想:解耦
图解:
编程模式:
Model(模式)
是应用程序中用于处理应用程序数据逻辑的部分
通常模型对象负责在数据库中存取数据
View(视图)
是应用程序中处理数据显示的部分
通常视图是依据模型数据创建的
Controller(控制器)
是应用程序中处理用户交互的部分
通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据
优点:
降低各功能模块之间的耦合性,方便变更,更容易重构代码,最大程度上实现代码的复用
MTV:
概述:本质上与MVC模式没有什么差别,也是各组件之间为了保持松耦合关系,只是定义上有些许不同
编程模式:
Model(模型):负责业务对象与数据库的对象(ORM)
Template(模版):负责如何把页面展示给用户
View(视图):负责业务逻辑,并在适当的时候调用Model和Template
注意:Django还有一个url分发器,它的作用是将一个个URL的页面请求 分发给不同的view处理,view再调用相应的Model和Template
二、Django创建项目
在合适位置创建一个文件夹
打开黑屏终端进入到上一步创建的文件夹目录下
输入命令:django-admin startproject project
目录层级说明:
manage.py:一个命令行工具,可以使我们用多种方式对Django项目进行交互
project目录:
__init__.py:一个空文件,它告诉python这个目录应该被看作一个python包
settings.py:项目的配置文件
urls.py:项目的URL声明
wsgi.py:项目与WSGI兼容的Web服务器入口
三、Django基本操作
1、设计表结构:这个不同的项目设计的表结构不同,这里不详细说
2、配置数据库
启动数据库:net start mysql
注意:Django默认使用的是SQLite数据库
在settings.py文件中,通过DATABASES选项进行数据库配置
配置MySQL:
python3.x安装的是PyMySQL
在__init__.py文件中写入两行代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import pymysql 2 pymysql.install_as_MySQLdb()
格式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 DATABASES = { 2 'default': { 'ENGINE':'django.db.backends.mysql', 3 'NAME': "数据库名", 4 'USER': '用户名', 5 'PASSWORD': '数据库密码', 6 'HOST': '数据库服务器IP', 7 'PORT': '端口', 8 } 9 }
3、创建应用
在一个项目中可以创建多个应用,每个应用进行一种业务处理
打开黑屏终端进入上次创建文件夹下的project目录
执行命令:python manage.py startapp myApp
myApp目录说明:
admin.py:站点配置
models.py:模型
views.py:视图
4、激活应用
在settings.py文件中,将myApp应用加入到INSTALLED_APPS选项中
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 INSTALLED_APPS = [ 2 'django.contrib.admin', 3 'django.contrib.auth', 4 'django.contrib.contenttypes', 5 'django.contrib.sessions', 6 'django.contrib.messages', 7 'django.contrib.staticfiles', 8 'myApp', 9 ]
5、定义模型
概述:有一个数据表,就对应有一个模型
在models.py文件中定义模型
引入from django.db import models
模型类要继承models.Model类,代码如下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from django.db import models 2 3 # Create your models here. 4 5 class Grades(models.Model): 6 # 定义模型类 7 gname = models.CharField(max_length=20) 8 gdate = models.DateTimeField() 9 ggirlnum = models.IntegerField() 10 gboynum = models.IntegerField() 11 isDelete = models.BooleanField(default=False) 12 13 class Students(models.Model): 14 sname = models.CharField(max_length=20) 15 sgender = models.BooleanField(default=True) 16 sage = models.IntegerField() 17 scontend = models.CharField(max_length=20) 18 isDelete = models.BooleanField(default=False) 19 # 关联外键 20 sgrade = models.ForeignKey('Grades')
说明:不需要定义主键,在生成时自动添加,并且值为自动增加
6、在数据库中生成数据表
生成迁移文件:
执行命令:python manage.py makemigrations
在migrations目录下生成一个迁移文件,此时,数据库中还没有生成数据表
执行迁移:
执行命令:python manage.py migrate 相当于执行SQL语句创建数据表
7、测试数据操作
进入到python shell:
执行命令:python manage.py shell
引入包:
1 from myApp.models import Grades,Students 2 from datetime import * 3 from django.utils import timezone
查询所有数据:
语法:类名.objects.all()
示例:Grades.objects.all()
添加数据:
本质:创建一个模型类的对象实例
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 >>> grade1 = Grades() 2 >>> grade1.gname = "python04" 3 >>> grade1.gdate = datetime(year=2017,month=7,day=17) 4 >>> grade1.ggirlnum = 3 5 >>> grade1.gboynum = 70 6 >>> grade1.save()
查看某个对象:
语法:类名.objects.get(pk=2)
示例:Grades.objects.get(pk=2)
修改数据:
语法:模型对象.属性 = 新值
示例: 1 >>> grade2.gboynum = 60 2 >>> grade2.save()
删除数据:
语法:模型对象.delete()
示例:grade2.delete()
注意:物理删除,数据库中的表里面的数据永久被删除
关联对象:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 >>> grade1 = Grades.objects.get(pk=1) 2 >>> stu = Students() 3 >>> stu.sname = "薛艳梅" 4 >>> stu.sgender = False 5 >>> stu.sage = 20 6 >>> stu.scontend = "我叫薛艳梅" 7 >>> stu.sgrade = grade1 8 >>> stu.save()
获得关联对象的集合:
需求:获取python04班级的学生
语法:对象名.关联的类名小写_set.all()
示例:grade1.students_set.all()
创建关联对象:
stu3 = grade1.students_set.create(sname="曾志伟",sgender=True,scontend="我叫曾志伟",sage=45)
注意:直接添加到数据库中
8、启动服务器
格式:python manage.py runserver ip:port
ip可以不写,不写的话代表本机ip
端口号默认是8000
说明: 这是一个纯python写的轻量级web服务器,仅仅在开发测试中使用
9、Admin站点管理
概述:内容发布(负责添加、修改删除内容)、公告访问
配置admin应用:
在settings.py文件中的INSTALLED_APPS中添加'django.contrib.admin',
默认是已经添加的
创建管理员用户:
执行命令:python manage.py createsuperuser
依次输入用户名、邮箱、密码
汉化:
修改settings.py文件
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
管理数据表:
修改admin.py文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from .models import Grades,Students 2 admin.site.register(Grades) 3 admin.site.register(Students)
自定义管理页面
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from .models import Grades,Students 2 # 注册 3 class GradesAdmin(admin.ModelAdmin): 4 # 列表页属性 5 list_display = ['pk', 'gname', 'gdate', 'ggirlnum', 'gboynum', 'isDelete'] 6 list_filter = ['gname',] 7 search_fields = ['gname'] 8 list_per_page = 5 9 # 添加、修改页属性 10 # fields = ['ggirlnum', 'gboynum', 'gname', 'gdate', 'isDelete'] 11 fieldsets = [ 12 ('num', {'fields':['ggirlnum', 'gboynum']}), 13 ('base', {'fields':['gname', 'gdate', 'isDelete']}) 14 ] 15 admin.site.register(Grades, GradesAdmin)
属性说明
列表页属性
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 list_display 显示字段 2 list_filter 过滤字段 3 search_fields 搜索字段 4 list_per_page 分页
添加、修改页属性
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 fields 规定属性的先后顺序 2 fieldsets 给属性分组 3 注意:fields与fieldsets不能同时使用
关联对象
需求:在创建一个班级时可以直接添加几个学生
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class StudentsInfo(admin.TabularInline): # StackedInline 2 model = Students 3 extra = 2 4 class GradesAdmin(admin.ModelAdmin): 5 inlines = [StudentsInfo]
布尔值显示问题
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class StudentsAdmin(admin.ModelAdmin): 2 def gender(self): 3 if self.sgender: 4 return '男' 5 else: 6 return '女' 7 # 设置页面列的名称 8 gender.short_description = "性别" 9 list_display = ['pk', 'sname', 'sage', gender, 'scontend', 'sgrade', 'isDelete'] 10 list_per_page = 10 11 admin.site.register(Students, StudentsAdmin)
执行动作位置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class StudentsAdmin(admin.ModelAdmin): 2 def gender(self): 3 if self.sgender: 4 return '男' 5 else: 6 return '女' 7 # 设置页面列的名称 8 gender.short_description = "性别" 9 list_display = ['pk', 'sname', 'sage', gender, 'scontend', 'sgrade', 'isDelete'] 10 list_per_page = 10 11 # 执行动作的位置 12 actions_on_top = False 13 actions_on_bottom = True 14 admin.site.register(Students, StudentsAdmin)
使用装饰器完成注册
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 @admin.register(Students) 2 class StudentsAdmin(admin.ModelAdmin): 3 def gender(self): 4 if self.sgender: 5 return '男' 6 else: 7 return '女' 8 # 设置页面列的名称 9 gender.short_description = "性别" 10 list_display = ['pk', 'sname', 'sage', gender, 'scontend', 'sgrade', 'isDelete'] 11 list_per_page = 10 12 # 执行动作的位置 13 actions_on_top = False 14 actions_on_bottom = True 15 # admin.site.register(Students, StudentsAdmin)
10、视图的基本使用
概述:在django中视图对web请求进行回应,视图就是一个python函数,在views.py文件中定义
定义视图:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from django.http import HttpResponse 2 def index(request): 3 return HttpResponse("dylan is a good man")
配置URL:
修改project目录下的urls.py文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from django.contrib import admin 2 from django.conf.urls import url,include 3 urlpatterns = [ 4 url(r'^admin/', admin.site.urls), 5 url(r'^', include('myApp.urls')), 6 ]
在myApp应用目录下创建一个urls.py文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from django.conf.urls import url 2 from . import views 3 urlpatterns = [ 4 url(r'^$', views.index) 5 ]
11、模版的基本使用
概述:模版是HTML页面,可以根据视图中传递过来的数据进行填充
创建模版目录:创建templates目录,在目录下创建对应项目的模版目录(工程project/templates/myApp)
配置模版路径:
修改settings.py文件下的TEMPLATES,'DIRS': [os.path.join(BASE_DIR, 'templates')]
四、Django模型
概述:Django对各种数据库提供了很好的支持,Django为这些数据库提供了统一的调用API,可以根据不同的业务需求选择不同的数据库
配置数据库:
修改工程目录下的__init__.py文件
1 import pymysql 2 pymysql.install_as_MySQLdb()
修改settings.py文件
1 DATABASES = { 2 'default': { 3 'ENGINE': 'django.db.backends.mysql', 4 'NAME': "ying", 5 'USER': 'root', 6 'PASSWORD': '123456', 7 'HOST': 'localhost', 8 'PORT': '3306', 9 } 10 }
开发流程:
配置数据库
定义模型类:一个模型类都在数据库中对应一张数据表
生成迁移文件
执行迁移文件生成数据表
使用模型类进行增、删、改、查(简称crud)操作
ORM:
概述:对象--关系--映射
任务:
根据对象的类型生成表结构
将对象、列表的操作转换成SQL语句
将SQL语句查询到的结果转换为对象、列表
优点:极大的减轻了开发人员的工作量。不需要面对因数据库的变更而修改代码
图解:
定义模型:
模型、属性、表、字段间的关系:
一个模型类在数据库中对应一张表,在模型类中定义的属性,对应该模型对照表中的一个字段
定义属性:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
定义属性 概述 .django根据属性的类型确定以下信息 .当前选择的数据表支持字段的类型 .渲染管理表单时使用的默认html文件 .在管理站点最低限度的验证 .gjango会为表增加自动增长的主键列,每个模型只能有一个主键列, 如果使用选项设置某属性为主键列后,则django不会再生成默认的主键列 .属性命名限制 .遵循标识符规则 .由于django的查询方式,不允许使用连续的下划线 库 .定义属性时,需要字段类型,字段类型被定义在django.db.models.fields 目录下,为了方便使用,被导入到django.db.models中 .使用方式 .导入from django.db. import models .通过models.Field创建字段类型的对象,赋值给属性 逻辑删除 .对于重要数据都要做逻辑删除,不做物理删除,实现方法是定义isDelete属性, 类型为BooleanField,默认值为False 字段类型 .AutoField .一个根据实际ID自动增长的IntegerField,通常不指定如果不指定 一个主键字段将自动添加到模型中 .CharField(max_length=字符长度) .字符串,默认的表单样式是TextInput .TextField .大文本字段,一般超过4000使用,默认的表单控件是Textarea .IntegerField .整数 .DecimalField(max_digits=None, decimal_places=None) .使用python的Decimal实例表示的十进制浮点数 .参数说明 .DecimalField.max_digits .位数总数 .DecimalField.decimal_places .小数点后的数字位数 .FloatField .用python的float实例来表示的浮点数 .BooleanField .true/false 字段,此字段的默认表单控制是CheckboxInput .NullBooleanField .支持null、true、false三种值 .DateField([auto_now=False, auto_now_add=False]) .使用python的datetime.date实例表示的日期 .参数说明 .DateField.auto_now .每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改" 的时间戳,它总是使用当前日期,默认为false .DateField.auto_now_add .当对象第一次被创建时自动设置为当前时间,用于创建的时间戳,它总是 使用当前日期,默认为false .说明 .该字段 默认对应的表单控件是一个TextInput,在管理员站点添加了一个 JavaScript写的日历控件,和一个"Today"的快捷按钮,包含了一个额外的 invalid_date错误消息键 .注意 .auto_now_add, auto_now, and default这些设置是相互排斥的,他们之间的 任何组合将会发生错误的结果 .TimeField .使用python的datetime.time实例表示的时间,参数同DateField .DateTimeField .使用python的datetime.datetime实例表示的日期和时间,参数同DateField .FileField .一个上传文件的字段 .ImageField .继承了FileField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image 字段选项 .概述 .通过字段选项,可以实现对字段的约束 .在字段对象时通过关键字参数指定 .null .如果为True,Django将空值NULL存储到数据库中,默认值是False .blanke .如果为True,则该字段允许为空白,默认值是False .注意 .null是数据库范畴的概念,blank是表单验证范畴的概念 .db_column .字段的名称,如果未指定,则使用属性的名称 .db_index .若值为True,则在表中会为此字段创建索引 .default .默认值 .primary_key .若为True,则该字段会成为模型的主键字段 .unique .如果为True,这个字段在表中必须有唯一值 关系 .分类 .ForeignKey:一对多,将字段定义在多的端中 .ManyToManyField:多对多,将字段定义在两端中 .OneToOneField:一对一,将字段定义在任意一端中 .用一访问多 .格式 .对象.模型类小写_set .示例 grade.students_set .用一访问一 .格式 .对象.模型类小写 .示例 .grade.students .访问id .格式 .对象.属性_id .示例 .student.sgrade_id
创建模型类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Students(models.Model): 2 # 定义一个类方法创建对象,cls代表了Students类 3 @classmethod 4 def createStudent(cls, name, age, gender, contend, grade, lastT, createT, isD=False): 5 stu = cls(sname=name, sage=age, sgender=gender, scontend=contend, sgrade=grade, lastTime=lastT,creatTime=createT, isDelete=isD) 6 return stu 7 # 自定义模型管理器 8 # 当自定义模型管理器时,objects就不存在了 9 stuObj = models.Manager() 10 stuObj2 = StudentsManager()
元选项:
在模型类中定义Meta类,用于设置元信息
定义数据表名,推荐使用小写字母,如果不写,数据表名默认为项目名小写_类名小写
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Meta: 2 db_table="students" 3 ordering=['id']
对象的默认排序字段,获取对象的列表时使用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 ordering=['id'] 升序 2 ordering=['-id'] 降序
注意:排序会增加数据库的开销
指定一个主键,创建表时就不会自动生成id
模型成员:
类属性:
objects是Manager类型的一个对象,作用是与数据库进行交互,当定义模型类时没有指定管理器,则Django为模型创建一个名为objects的管理器
自定义管理器:
stuObj = models.Manager()
当为模型指定模型管理器,Django就不再为模型类生成objects模型管理器
自定义管理器Manager类:
模型管理器是Django的模型与数据库进行交互的接口,一个模型可以有多个模型管理器
作用:
向管理器类中添加额外的方法
修改管理器返回的原始查询集(重写get_queryset()方法)
代码示例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class StudentsManager(models.Manager): 2 def get_queryset(self): 3 return super(StudentsManager,self).get_queryset().filter(isDelete=False) 4 5 class Students(models.Model): 6 # 自定义模型管理器 7 # 当自定义模型管理器时,objects就不存在了 8 stuObj = models.Manager() 9 stuObj2 = StudentsManager()
创建对象:
目的:向数据库中添加数据
当创建对象时,Django不会对数据库进行读写操作,当调用save()方法时才与数据库交互,将对象保存到数据库表中
注意:__init__()方法已经在父类models.Model中使用,在自定义的模型中无法使用
方法:
在模型类中增加一个类方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Students(models.Model): 2 # 定义一个类方法创建对象,cls代表了Students类 3 @classmethod 4 def createStudent(cls, name, age, gender, contend, grade, lastT, createT, isD=False): 5 stu = cls(sname=name, sage=age, sgender=gender, scontend=contend, sgrade=grade, lastTime=lastT,creatTime=createT, isDelete=isD) 6 return stu
在定义管理器中添加一个方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class StudentsManager(models.Manager): 2 def get_queryset(self): 3 return super(StudentsManager,self).get_queryset().filter(isDelete=False) 4 # 在管理器中添加一个方法 5 def createStudent(self, name, age, gender, contend, grade, lastT, createT, isD=False): 6 stu = self.model() 7 stu.sname = name 8 stu.sage = age 9 stu.sgender = gender 10 stu.scontend = contend 11 stu.sgrade = grade 12 stu.lastTime = lastT 13 stu.creatTime = createT 14 stu.isDelete = isD 15 return stu
模型查询:
概述:
查询集:表示从数据库中获取的对象集合
查询集可以有多个过滤器
过滤器就是一个函数,基于所给的参数限制查询集结果
从sql角度来说,查询集和select语句等价,过滤器就像where条件
查询集:
在管理器上调用过滤器方法返回查询集
查询集经过过滤器筛选后产生新的查询集,所以可以写成链式调用
惰性执行:创建查询集不会带来任何数据的访问,直到调用数据时,才会访问数据
直接访问数据的情况:迭代、序列化、与if合用
返回查询集的方法称为过滤器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 all():返回查询集中的所有数据 2 filter():返回符合条件的数据 3 filter(键=值) 4 filter(键=值,键=值) 5 filter(键=值).filter(键=值) 6 exclude():过滤掉符合条件的数据 7 order_by():排序 8 values():一条数据就是一个对象(字典),返回一个列表
返回单个数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 get():返回一个满足条件的对象 2 注意:如果没有找到符合条件的对象,会引发"模型类.DoesNotExist"异常;如果找到多个对象,会引发"模型类.MultipleObjectsReturned"异常 3 count():返回当前查询集中的对象个数 4 first():返回当前查询集中的第一个对象 5 last():返回当前查询集中的最后一个对象 6 exists():判断查询集中是否有数据,如果有数据返回True,否则返回False 7
限制查询集:查询集返回列表,可以使用下标的方法进行限制,等同于sql中的limit语句
studentsList = Students.stuObj2.all()[0:5]
注意:下表不能是负数
查询集的缓存:
概述:每个查询集都包含一个缓存,来最小化的对数据库访问;在新建的查询集中,缓存首次为空,第一次对查询集求值,会发生数据缓存。django会将查询出来 的数据做一个缓存, 并返回查询结果,以后的查询直接使用查询集的缓存
字段查询:
概述:实现了sql中的where语句,作为方法filter()、exclude()、get()的参数
语法:属性名称__比较运算符=值
外键:属性名_id
转义:like语句中使用%是为了匹配占位。匹配数据中的%(where like "\%")
比较运算符:
exact:判断,大小写敏感 contains:是否包含,大小写敏感 startswith:以value开头,大小写敏感 endswith:以value结尾,大小写敏感 以上四个在前面加上 i,就表示不区分大小写iexact、icontains、istartswith、iendswith isnull、isnotnull:是否为空 in:是否包含在范围内 gt、gte、lt、lte:大于、大于等于、小于、小于等于 year、month 、day、week_day、hour、minute、second 跨关联查询: 处理join查询: 语法:模型类名_属性名_比较运算符 查询快捷:pk(代表的是主键)
聚合函数:
使用aggregate()函数返回聚合函数的值,还有Avg()、Count()、Max()、Min()、Sum()
F对象:可以使用模型的A属性与B属性进行比较
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from django.db.models import F 2 def grades(request): 3 g = Grades.objects.filter(ggirlnum__gt=F('gboynum')) 4 print(g) 5 return HttpResponse("************") 6 7 支持F对象的算术运算: 8 g = Grades.objects.filter(ggirlnum__gt=F('gboynum')+20)
Q对象:
概述:过滤器的方法中的关键字参数,条件为And模式
需求:进行or查询
解决:使用Q对象
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from django.db.models import Q 2 studentsList = Students.stuObj2.filter(Q(pk__lt=3) | Q(sage__gt=50)) 3 studentsList = Students.stuObj2.filter(Q(pk__lt=3)) #只有一个Q对象,就是用于匹配的 4 studentsList = Students.stuObj2.filter(~Q(pk__lt=3)) #取反