Django 1 django框架介绍 是一个开源框架,2005年发布,采用Python语言编写的,早期时主要做新闻和内容管理的网站 Django本身提供了非常强大的后台管理系统 看中文说明文档 百度【djangobook】 2 框架模式 MTV M:Models T:Templates V:views 3 查看安装的版本 交互模式中:django.VERSION 安装指定版本 pip3 install django==1.11.8 框架使用 1 创建项目 使用 django-admin 创建Django项目 语法:django-admin startproject 项目名称 2 Django的项目结构介绍 1 manage.py 功能:包含执行django中的各项操作的指令 如: 启动服务:runserver 2 主目录(与项目名称一致的目录) 1 __init__.py 项目的初始化文件,自动运行 2 urls.py 项目的基础路由配置文件 3 wsgi.py Web Server Gateway Interface Web 服务网关接口 4 settings.py 项目的配置文件 1 BASE_DIR 2 ALLOWED_HOSTS 设置允许访问到本项目的地址列表,如果允许在网络中被其他的机器访问到的话 推荐写['*'],表示任何能够表示该机器的地址都能访问到该项目 同时还需配合着启动服务时要指定地址和端口 python3 manage.py runserver 0.0.0.0:8000 3 INSTALLED_APPS 指定已安装的应用,如果有自定义的应用的话,需要在此注册 4 MIDDLEWARE 中间件,如果有自定义的中间件的话,需要在此注册 5 ROOT_URLCONF 指定项目的基础路由配置文件 6 TEMPLATES 配置模板的信息 7 DATABASES 配置数据库的信息 8 LANGUAGE_CODE 语言设置,如果需要中文的话,允许将值更改为'zh-Hans' 9 TIME_ZONE 指定时区,中国的时区,允许将值更改为“ Asia/Shanghai” 3 url的使用 1 urls.py 默认是在主目录中,主路由配置文件,会包含最基本的地址映射,并且每个地址访问都必须要先经过该文件 作用:通过urls中定义好的地址找到对应的视图处理函数 2 url() 的语法 作用:为了匹配用户的访问路径 语法: from django.conf.urls import url url(regex,views,kwarg=None,name=None) 1 regex:允许是正则表达式,匹配请求的url 1 regex 支持正则表达式 通过 regex 配置参数,通过正则表达式的子组传递参数 一个子组-(),视为一个参数,多参数之间使用 / 分隔 对应的视图处理函数中也需要定义参数来接收地址栏传递过来的参数 2 views:地址匹配后要执行操作的视力处理函数 3 kwarg:字典,用来向views传参的,可以省略 4 name:为url起别名,在地址反向解析时使用 #编写视力处理函数 # 语法: def 函数名(request): # pass 3 通过url 向视图传参 1 使用正则表达示传参 使用子组传参,一个子组是一个参数,要传递多个参数的话需要使用多个子组,中间用 / 隔开 子组 -() urlpatterns = [ # 访问路径是 /02-show/ 四位数字,交给show02_views去处理 url(r'^02-show/[0-9]{4}/',show02_views) ] 2 使用url()第三个参数 - 字典传参 dic = { "name":"sasuke", "age":18 } url(r'^show/$',show_views,dic) def show_views(request,name,age) name:字典中name的值,字符串 age:字典中name的值,整数 pass 4 django中的应用 1 什么是应用 应用就是网站中的一个独立的程序模块 如:网易网站可分为若干应用组成: 1 新闻应用 - 与新闻相关的内容 2 汽车应用 - 与汽车相关的内容 ... 在django中,主目录一般不处理具体的请求,主目录一般要处理的是项目中的初始化操作以及请求的分发(分布式请求处理), 而具体的请求是由各个应用去处理。 2 创建应用 1 指令 ./manage.py startapp 应用名称 2 在settings.py中进行注册 在INSTALLED_APPS 中追加应用的名称来表示注册应用 INSTALLED_APPS = [ 'django.contrib.admin', ... , "自定义应用名称" ] 3 应用的结构组成 1 migrations 文件夹 存放数据库的中间文件 2 __init__.py 应用的初始化文件 3 admin.py 应用的后台管理配置文件 4 app.py 应用的属性配置文件 5 models.py Models 与模型相关的映射文件 6 tests.py 应用的单元测试文件 7 views.py 定义视图处理函数的文件 4 分布式路由系统 在每个应用中分别去创建 urls.py 格式参考主路由文件 目的:为了处理各个应用中的请求路由 当访问路径时 http://locahost:8080/music/xxx 则交给music的urls去处理 ==================== 1 路由配置 1 访问路径是 http://locahost:8000/music/ 想交给music 应用中的index_views 2 django中的模板 - Templates 1 什么是模板 模板就是要动态呈现给用户的网页 模板的本质就是网页 - 前后端,动静结合的网页 django中的模板引擎是由django自己提供的,而并非jinjia2, 所以django的模板语法与Flask的语法会稍有不同 2 模板的设置 在 settings.py 中设置 TEMPLATES 变量 1 BACKEND: 指定使用的模板的引擎 2 DIRS: 指定模板的存放目录们 1 'DIRS': [os.path.join(BASE_DIR, 'templates')] 在项目的根目录的templates目录中存放所有的模板 2 DIRS:['INDEX.temp','music.temp'] 在项目的index 应用中的temp目录中存放模板 以及 在项目的music应用中的temp目录中存放模板 3 APP_DIRS:表示是否自动搜索应用中的目录 True:表示要自动搜索应用中的templates 的目录 3 模板的加载方式 1 通过loader对象获取模板,再通过HttpResponse进行响应 1 先导入 loader from django.template import loader 2 通过loader 加载模板 t = loader.get_templates('模板名称') t : 为在django中得到的模板对象 3 将加载好的模板渲染成字符串 html = t.render() 4 通过HttpResponse将字符串进行响应 return HttpResponse(html) 2 使用render直接加载并响应模板 return render(request,'模板名称') 4 模板的语法 1 变量 1 作用:将后端的数据传递到模板进行显示 2 允许作为变量的数据类型 字符串,整数,列表,元组,字典,函数,对象 3 变量的语法 变量们必须要封装到字典中才能传递给模板 4 渲染 1 使用render 加载模板 return render(request,'xxx.html',dic) 5 在模板中使用变量 {{变量名}} 2 标签 1 作用 将服务器端的功能嵌入到模板中 2 语法: {% 标签名 %} ... {% end标签名 %} 3 常用标签 1 {% if %} 1 {% if 条件%} ... {% endif%} 2 {% if 条件%} 满足条件要执行的内容 {% else %} 不满足条件要执行的内容 {% endif %} 3 {% if 条件1 %} {% elif 条件2 %} {% elif 条件3 %} {% else %} {% endif %} 2 {% for %} 语法: {% for 变量 in 列表|元组|字典 %} .. {% endfor %} 内置变量:forloop 在循环中允许使用forloop内置变量来获取循环的信息 forloop.counter:记录当前循环遍历的次数 forloop.counter0:记录当前循环遍历的次数,从0开始 forloop.revcount:记录当前元素从后向前算的位置 forloop.revcount0:同上,从0开始记录 forloop.first:判断是否是第一次循环 forloop.last:判断是否是最后一次循环 3 过滤器 1 什么是过滤器 在变量输出显示之前,对变量的数据进行筛选和过滤 2 过滤器的语法 {{变量|过滤器:参数}} 3 常用过滤器 1 {{value|upper}} 将value变为大写 2 {{value|lower}} 将value变为小写 3 {{value|add:num}} 将num追加到value之后 value 和 num 也可以是列表 4 {{value|floatformat:n}} 将value四舍五入到n位小数 5 {{value|truncatechars:n}} 将value截取保留至n位字符,后面以...来表示未显示完成的内容 4 静态文件 1 什么是静态文件 无法与服务器进行动态交互的文件就是静态文件 2 在django中的静态文件的处理 在settings.py 中设置有关静态文件的信息: 1 设置静态文件的访问路径 在浏览器中通过哪个地址能够找到静态文件 STATIC_URL = '/static/' 如果访问路径是http://locahost:8000/static/... 一律都按照静态文件的方式去查找 2 设置静态文件的存储路径 指定静态文件要保存在服务器上哪个目录处 STATICFILES_DIRS=(os.path.join(BASE_DIR,'static'),) 静态文件目录的存放位置: 1 在项目的根目录处创建一个 static 目录,用于保存静态文件们 2 每个应用中也可以创建一个 static 目录,用于保存静态文件们 3 直接使用静态文件访问路径进行访问 1 http://locahost:8000/static/... ex: <img src=/static/images/b.jpg'> 2 使用 {% static %} 访问静态资源 1 在使用之前需要通过{% load static %} 加载static 2 使用静态资源时 <img src="{% static 'images/b.jpg'%}"> =================== 1 模板的继承 1 语法: 1 在父模板中 必须标识出来哪些内容在子模板中允许被修改 标签 {% block 块名%} {% endblock%} block的作用: 1 在父模板中没有任何影响,正常显示 2 在子模板中,允许被修改,但如果不做任何修改的话,则会按照父模板的内容进行显示 2 在子模板中 1 指定继承自哪个父模板 {% extends '父模板名称'%} 2 通过block 标签,改写属于自己的内容 {% block 块名%} {% endblock%} 2 url()的name参数 - 反向解析 1 url的语法 name:为地址起别名,反向解析时使用 2 反向解析 1 在模板上做反向解析 1 基本解析 {% url '别名'%} 2 带参的解析 {% url '别名' '参数1' '参数2'%} 2 在视图上做反向解析 1 基本解析 url = reverse('别名') url 就是通过别名解析出来的地址 2 带参数的解析 url = reverse('别名',args=(参数1,参数2)) 2 模型 - Models 1 什么是模型 根据数据表结构而创建出来的class 2 ORM 对象关系映射(object Relational Mapping) 三大特征: 1 表到类的映射 2 数据类型的映射 3 关系映射 3 创建 和配置数据库 1 创建数据库 -webdb 2 django的数据库配置 在settings.py 中配置数据库的信息 1 ENGINE : 指定连接数据库的驱动程序 连接mysql的话可以取值为 'django.db.backends.mysql' 2 NAME:指定要连接到的数据库的名称 连接mysql的话可以取值为 数据库名 3 USER:指定登录到数据库管理系统的用户名 连接到mysql的话 可以为 root 4 PASSWORD:指定登录到数据库管理系统的密码 5 HOST:指定要连接到的主机地址 如果是本机的话:127.0.0.1 或 locahost 6 PORT :指定端口号 mysql 的默认为 3306 3 数据库的同步操作 1 ./manage.py makemigrations 作用:将每个应用下的models.py文件生成一个数据库的中间文件 并将中间文件保存到migrations的目录中 2 ./manage.py migrate 作用:将每个应用下的migrations目录中的中间文件同步到数据库中 4 编写 Models 1 举个例子 2 Models的语法规范 class className(models.Model): 属性 = models.FIELDTYPE(FIELD_OPTIONS) FIELDTYPE :字段类型 Charfield() FIELD_OPTIONS:字段选项(字段说明) max_length=30 字段类型: FIELDTYPE 1 BooleanField() 编程语言中使用True 或 False 来表示该列的值 数据库中使用1 或 0 来表示具体的值 数据类型为:tinyint 2 Charfield() 编程语言中使用字符串来表示该列的值 数据库中也是字符串 注意:必须要指定max_length参数值 3 DateField() 编程语言中使用字符串或Date类型的数据表示该值 数据库中使用的是时间字符串 数据类型为:date 4 DateTimeField() 数据类型为:datetime 5 DecimalField() 编程语言中使用数字(小数)来表示该列的值 数据库使用小数表示 数据类型:decimal money = models.DecimalField(max_digits=7,decimal_places=2) 6 FloatField() 编程语言中使用数字(小数)来表示该列的值 数据库使用小数 数据类型:float 7 IntegerField() 数据类型:int 8 EmailField() 编程语言中使用字符串来表示一段Email地址 数据库中使用 字符串表示 数据类型:varchar 9 URLField() 编程语言中使用字符串来表示一段网址 数据库中使用字符串表示 数据类型:varchar 10 ImageFiled() 目的:存储图片路径 数据类型:varchar image = models.ImageFiled(upload_to = 'images/')
image = models.ImageField(upload_to='static/upload/goodstype',verbose_name='图片') 字段选项: 1 default 作用:为当前字段指定默认值 2 null 作用:指定当前字段指定是否允许为空,默认为False,不能为空 3 db_index 作用:指定是否为当前字段指定索引 4 db_column 作用:指定当前属性映射到表中的类名,如果不指定则采用属性名称作为类名 ============= 1 模型 1 相关命令 1 版本切换命令 0001_initial.py 0002_xxxx.py python3 manage.py migrate 应用名称 版本号 2 通过数据库自动导出models类 python3 manage.py inspectdb > 文件名.py 2 模型中的CRUD 1 增加数据 1 Entry.objects.create(属性=值,属性=值) Entry是对应的实体类 返回值: 插入成功:则返回创建好的实体对象 插入失败:则返回 None (会伴随异常的产生) 2 创建一个Entry对象,并通过save()进行保存 obj = Entry(属性=值,属性= 值) obj.属性 = 值 obj.save() 无返回值,保存成功后,obj会被重新赋值 3 通过字典创建Entry对象,并通过save()进行保存 dic = {'属性1':'值1','属性2':'值2'} 2 查询数据(重难点) 通过Entry.objects 调用查询接口函数 Entry.objects.all() Entry.objects 提供了对该实体的所有的数据的查询 (没有去数据库查询) 所有的接口函数,都可以通过一个query 属性来得到所对应的sql语句 Entry.objects.all().query 1 获取所有查询结果 方法:all() 用法:Entry.objects.all() 返回:QuerySet(查询结果集,本质是一个封装了若干对象的列表) 2 查询返回指定列 方法:values() | values('列名1','列名2') 作用查询表中数据的部分列,封装到字典中,再封装到QuerySet中 返回:QuerySet(查询结果集,本质是一个封装了若干字典的列表) 3 查询返回指定列 方法:values_list() 作用:将数据封装到元组中,再封装到列表中 4 排序方法 方法:order_by() 语法:Entry.objects.order_by('列1','-列2') 默认是升序排序,列名值加 -,则表示降序排序 5 查询只返回一条数据 方法:get(条件) 注意: 该方法只适用于只能查询出一条结果的场合 如果查询多于一条数据或没有查询出结果都会抛出异常 6 根据条件查询部分行 方法: filter(条件) 返回:QuerySet ex: 1 查询Author 实体中 id =1 的信息 authoors = Author.objects.filter(id=1) 2 查询多条件(and) authonr = Author.objects.filter(id=1,age=24) 非等值条件需要使用Field Lookups(查询谓词) 语法:Entry.objects.filter(属性__查询谓词 = 值) 注意: 1 每个查询谓词都是一个独立的功能条件 __exact:等值条件判断 __gt:大于条件判断 __year:得到日期中的年份再进行进一步判断 __contaions:模糊查询"%xxx%" __range:模糊查询 between and ... ... 2 所有支持条件查询的位置处都支持查询谓词 filter(), get(), exclude() 7 对条件取反 方法:exclude(条件) ex: Author.objects.exclude(id=1) select * from index_author where not(id=1) 8 聚合查询(不带分组) 方法: aggregate(列名 = 聚合函数('列')) ex: Author.objects.aggregate(sumage=Sum('age')) 1 Avg(): 平均值 2 Count():数量 3 Sum():求和 4 Min():求最小值 5 Max():求最大值 9 聚合查询(带分组) 方法:annotate(名=聚合函数('列')) ex: 按id 分组,查询平均年龄 Author.objects.values('id').annotate(avgAge=Avg('age')).all() 按 isactive 进行分组,查看平均年龄 author = Author.objects.values('isactive').annotate(avgage=Avg('age')).all() 按 isactive 进行分组,查看平均年龄大于30的 Author.objects.values('isactive').annotate(avgage=Avg('age')).filter(avgage__gte=30).all() Author.objects.filter(id__gte=3).values('isactive').annotate(avgage=Avg('age')).filter(avgage__gte=30).all() 3 修改数据 1 修改单个实体 1 查 通过get() 查询出要修改的实体 2 改 通过实体对象save()方法保存数据回数据库 3 保存 通过实体对象save()方法保存数据回数据库 2 批量修改数据 调用QuerySet的update(属性=值,属性=值)实现批量修改 4 删除数据 调用实体对象/查询结果集的 delete()完成删除 1 删除单个对象 a = Author.objects.get(id=1) a.delete() 2 批量删除 aulist = Author.objects.all() aulist.delete() ==================== 1 模型 1 F查询 和Q查询 [更新时使用] 1 F() 作用:在执行过程中获取某列的值 语法: from django.db.models import F F('列名'):得到对应列的值 Author.objects.all().update(age = F('age')+10) 2 Q() 作用:在查询条件中可以完成 or 操作 from django.db.models import Q Q(条件1) | Q(条件2) 查询 id 大于等于3 或年龄 <40 的人的信息 2 原生的数据库的操作方法 1 查询 函数: raw() 语法 Entry.objects.raw(sql) 返回:QuerySet 2 增删改 from django.db import connection def doSql(request): with connection.cursor() as cursor: sql = "update index_author set age=age+10" cursor.execute(sql) 2 使用后台管理 Models 1 后台的配置 ./admin 创建后台管理员(超级用户): python manage.py createsuperuser Username:输入用户名,默认为系统账户名 Email Address: 电子邮件 Password : 密码 Password(again):确认密码 2 admin.py 中注册要管理的实体类 作用:注册要管理的Models类,只有注册后才能管理 3 注册 Models from .models import * admin.site.register(Entry) admin.site.register(Author) 4 修改 Models提升可读性 1 重写每个实体类中的 __str__() 后台显示的将以 __str__ 的返回值为准 def __str__(self): return '<Author %r>'%self.name 2 为实体类中的属性们增加字段选项 - verbose_name 用于修改显示的字段名 5 通过Models类的内部类Meta定义其展现形式 class Author(models.Model): ... class Meta 1 db_table 指定该实体类映射到的表的名称 (该属性设置完成后需要同步回数据库) 2 verbose_name 定义类在admin 中显示的名字(单数) 3 verbose_name_plural 定义类在 admin 中显示的名字(复数) ex: class Meta: #映射到表的名称 db_table = 'author' # 定义在后台的显示名称(单数) verbose_name = '作者' #定义在后台的显示名称(复数) verbose_name_plural=verbose_name 4 ordering 指定数据在后台管理中显示的排序方式 取值为一个列表,指定排序列,降序使用- ex: class Meta: #定义数据在后台的排序方式 ordering=['-age','id'] 3 Models 的高级管理 1 在admin.py中创建高级管理类并注册 1.定义 Entry 类,继承自 admin.ModelAdmin class AuthorAdmin(admin.ModelAdmin): pass 2 注册高级管理类 admin.site.register(Entry,EntryAdmin) ex: admin.site.register(Author,AuthorAdmin) 2 允许在 EntryAdmin中增加的属性 1 list_display 作用:定义在列表页上显示的字段们 取值:由属性名组成的元组或列表 2 list_display_links 作用:定义在列表页上也能够链接到详情页的字段们 取值:同上 注意:取值必须要出现在list_display中 3 list_editable 作用:定义在列表页上就能够修改的字段们 取值:同上 注意:取值必须出现在 list_display中,但不能出现在list_display_links中 4 search_fields 作用:定义搜索栏中允许搜索栏中允许搜索的字段值们 取值:同上 5 list_filter 作用:列表页的右侧在增加过滤器实现快速筛选 取值:同上 6 date_hierarchy 作用: 列表页的顶部增加一个时间选择器, 取值 :属性必须是DateField或 DateTimeField的列 7 fields 作用:在详情页中,指定要显示哪些字段并按照什么样的顺序显示 取值:由属性名组成的元组或列表 8 fieldsets 作用:在详情页面中对字段们进行分组显示 注意:fieldset 与 fields 不能共存 取值: fieldsets=( #分组1 ('分组名称',{ 'fields':('属性1','属性2'), 'classes':('collapse',) }), #分组2 () ) ex: class AuthorAdmin(admin.ModelAdmin): #1 定义显示在列表页上的字段们 list_display = ('name','age','email') # 2 定义允许链接到详情页的字段们 list_display_links =('age','email') # 3 定义在列表页中就允许修改的字段们 list_editable = ('name',) # 4 定义搜索字段 search_fields = ('name','age') # 5定义右侧过滤器 list_filter=('name','age') # 7 指定在详情页上显示的字段以及顺序 # fields = ('name','email') # 8 指定字段们在详情页上的分组 fieldsets = ( #分组1 ('基本信息',{'fields':('name','age'), 'classes':('collapse',)}), ('详细信息',{'fields':('age','email'), 'classes':('collapse',)}) ) class BookAdmin(admin.ModelAdmin): #指定在列表页中的显示的字段们 list_display = ('title','publicate_date') #6 增加时间选择器 date_hierarchy = ('publicate_date') admin.site.register(Author,AuthorAdmin) admin.site.register(Book,BookAdmin) 4 关系映射 1 关系映射 1 一对一映射 1 语法: 在关联的两个类中的任何一个类都可以增加对另一个类的引用 属性 = models.OneToOneField(Entry) ex: class Author(models.Model): ... ... class Wife(models.Model): ... ... # 增加对Author的一对一引用 author = models.OneToOneField(Author) 在数据库中: 会生成一个外键(authonr_id)列在 wife 表中, 会引用在 authonr 表的主键 在 Author 中: 增加一个隐式属性 - wife, 来表示author 所对应的 wife(其实就是反向引用属性) 2 查询 1 正向查询:通过 Wife 找 Author 特点:通过自定义的关联属性查找对应实体 wife = Wife.objects.get(id=1) authonr = wife.author 2 反向查询:通过 Author 找 Wife 特点:通过反向引用属性查找对应的实体 authonr = Author.objects.get(id=1) wife = authonr.wife 2 一对多映射 1 语法 在"多"表中增加对“一”表的外键引用 在"多" 实体中增加对"一"实体的引用 在"多"实体中增加: 属性 = models.ForeignKey(Entry) ex: [ Book 和 Publisher ] class Book(models.Model) ... ... publisher = models.ForeignKey(Publisher) 数据库体现: Book 表中 增加一个外键列 publisher_id ,引用自Publisher 表中的主键 在实体类中的: 1 BOOK中会有一个 publisher 属性 来表示对应的 Publisher的对象 2 Publisher 中会有一个隐式属性 - book_set,用来表示该 publisher 对应所有的BOOK 对象的查询 3 多对多映射 1 语法 在关联的两个类的任意一个类中,增加: 属性 = models.ManyToManyField(Entry) ex:Author 与 Book 可以是多对多的关联关系 1位Author可以出版多本Book 1本Book可以由多位Author联合编写 class Author(models.Model): .... class Book(models.Model): ... authonrs = models.ManyToManyField(Author) 正向引用: 在Book中通过 authonrs 来表示对应的所有的书籍的查询 反向引用: 在Author 中通过 book_set 来表示对应的所有的作者们的查询 2 自定义查询函数 1 声明EntryManager类,继承自 models.Manager 允许在EntryManager中增加自定义函数 class EntryManager(models.Manager): def 函数名(self,自定义参数): ... return ... 2 使用EntryManager对象覆盖Models类中原有的objects class Entry(models.Model): objects = EntryManager() # 自定义AuthorManager类型,继承自models.Manager # 并定义自定义方法 class AuthorManager(models.Manager): def isactive_count(self): # 查询isactive=True的数量是多少 return self.filter(isactive=True).count() 5 HTTPRequest - 请求 1 什么是HTTPRequest HTTPRequest,就是对请求对象的封装,里面封装的是请求过程中的所有信息。 在DJango中 HTTPRequest被封装成request对象并封装到视图处理函数中,在调用视图时自动传入 2 HTTPRequest中的主要内容 1 request.scheme : 请求协议 2 request.body :请求主体 3 request.path :请求路径 4 request.get_full_path() :请求完整的请求路径 5 request.get_host():请求的主机地址 / 域名 6 request.method 7 request.GET: 封装了 get请求方式所提交的数据 8 request.POST :封装了 post 请求方式所提交的数据 9 request.COOKIES:封装了 cookies中的所有数据 10 request.META: 封装了请求的元数据 request.META.HTTP_REFERER:封装了请求的源地址 3 获取请求提交的数据 1 .get请求方式所提交的数据 request.GET['名称'] request.GET.get('名称') request.GET.getlist('名称') 2 get方式提交数据的场合 1 表单中method 为get 的时候 2 地址栏上拼查询字符串的时候 http://locahost:8000/index?id=xxx 3 使用post方式提交数据的场合 1 使用表单提交可以使用post 2 CSRF verification failed(403) CSRF: Cross-Site Request Forgery 跨 站点 请求 伪装 解决方案: 1 取消csrf的验证 删除 settings.py中 MIDDLEWARE中的 CsrfViewMiddleware的中间件 2 在处理函数上增加装饰器 @csrf_protect(需要自己手动写,也不是较好的解决方案) 3 可以在表单中的 第一行增加:{%csrf_token%} 3 使用forms 模块处理表单 1 forms模块的作用 通过forms模块,允许将表单与class结合(表单与实体类结合),允许通过class生成表单 2 使用forms模块 1 在应用中创建 froms.py 文件 2 导入forms 模块 from django import forms 3 创建class,一个class对应生成一个表单 class ClassName(forms.form); pass 4 创建属性 一个属性对应到表单中生成一个控件 class RemarkForm(forms.Form): #评论标题 subject = forms.CharField(label='标题') #电子邮箱 emails = forms.EmailField(label='电子邮箱') # 评论内容,widget=forms.Textarea将当前的单行文本框变为多行文本域 message = forms.CharField(label='评论内家',widget=forms.Textarea) # 评论级别 topic = forms.ChoiceField(label='级别',choices=TOPIC_CHOICE) # 是否保存 - 复选框 isSaved = forms.BooleanField(label='是否保存') 2 处理方法 1 在 views 中创建 form 的对象并发送到模板上 form = RemarkForm() return render(request,'xxx.html',locals()) 2 在模板中进行解析 1 手动解析 {%for field in form %} {{field}}: 表示的就是form对象中的一个独立属性 表示的也就是一个独立的控件 {{ field.label}}: 表示的是控件中的label的值 {% endfor %} ### <form action="" method="post"> {% for field in form %} <p> {{ field.label }}:{{ field }} </p> {% endfor %} <input type="submit"> {% csrf_token %} </form> ### 2 自动解析 1 {{ form.as_p }} 将form对象中的每个属性使用 p 标记包裹起来再显示 2 {{form.as_ul}} 将form对象中的每个属性使用 li 标记包裹起来再显示 注意:必须手动提供<ol> 或 <ul> 3 {{ form.as_table}} 将form对象中的每个属性用tr 标记包裹起来再显示,再显示 注意:必须手动提供<table> 1 使用 forms 模块 1 通过 forms.form 获取表单数据 - POST 1 通过 forms.Form 的构造函数来接收 post数据 form = xxxForm(request.POST) 2 必须使 form通过验证后再获取数据 form.is_valid() 返回True :提交的数据以及表单已通过所有的验证,允许取值 取值: 返回False:未通过验证,则不能正常取值 3 获取表单中的数据 通过 form.cleaned_data 来获取提交的数据 【 1 将request.POST的数据提交给RemarkForm form = RemarkForm(request.POST) 2 让RemarkForm的对象通过验证 (必须要先验证再调用cleaned_data,否则会报错) if form.is_valid(): cd = form.cleaned_data return HTTPResponse('OK') 3 通过验证后再获取各个控件的值 】 1 使用 forms 模块 1 通过 forms.Form 获取表单数据 -POST 2 forms 模块的高级处理 将 Models 和 Forms 结合到一起使用 1 在forms.py 中创建class,继承自 forms.ModelForm 2 创建内部类Meta,去关联 Model 1 model: 指定要关联的实体类 2 fields: 指定从 Models中取哪些字段生成控件 1 取值 "__all__",表示全部属性都要生成控件 2 取值 列表,声明允许生成控件的属性名 3 labels :指定每个属性所关联的label,取值为字典 labels={ "属性名":"label文本", "属性名":"label文本", } ex: class RegisterForm(forms.ModelForm): class Meta: # 1 指定关联的Model是谁 model = Author # 2 指定生成控件的字段们 fields = "__all__" # 3 指定每个控件对应的label labels={ "name":"用户名称", "age":"用户年龄", "email":"用户邮箱", "isactive":"是否激活" } 3 内置小部件 - widget 1 什么是小部件 小部件,表示的就是生成到网页上的控件类型以及其他的html属性 2 常用小部件类型 1 TextInput:type = 'text' 2 PasswordInput:type = "password" 3 NumberInput:type ="number" 4 EmailInput :type="email" 5 URLInput :type= 'url' 6 HiddenInput:type="hidden" 7 CheckboxInput:type='checkbox' 8 Textarea: <textarea></textarea> 9 Select : <select></select> 3 小部件的使用 1 继承自forms.Form 类 1 基本版 只指定控件的类型 class RemarkForm(forms.Form): #评论标题 subject = forms.CharField(label='标题', widget = forms.小部件类型 ) 2 高级版 指定控件类型的基础上还允许设置一些 相关的HTML属性到控件上 属性 = forms.CharField( label='文本', widget=forms.小部件类型(attrs ={ "html属性名":"属性值", "html属性名":"属性值", }) ) 2 继承自 forms.ModelForm类 class xxxForm(forms.ModeForm): class Meta: model=xxx fields = "__all__" 或[] labels = {"属性1 ":"标签1",} #指定小部件 widets = { } 示例 from django import forms from .models import * #表示评论内容控件的class # 控件1 评论标题 -文本框 # 控件2 电子邮箱 - 邮件框 # 控件3 评论内容 - Textarea # 控件4 评论级别 -下拉选择框 # 控件5 是否保存 - 复选框 TOPIC_CHOICE=(('1','好评'),('2','中评'),('3','差评')) class RemarkForm(forms.Form): #评论标题 subject = forms.CharField(label='标题') #电子邮箱 emails = forms.EmailField(label='电子邮箱') # 评论内容,widget=forms.Textarea将当前的单行文本框变为多行文本域 message = forms.CharField(label='评论内家',widget=forms.Textarea) # 评论级别 topic = forms.ChoiceField(label='级别',choices=TOPIC_CHOICE) # 是否保存 - 复选框 isSaved = forms.BooleanField(label='是否保存') class Userinfo(forms.Form): name = forms.CharField(label='姓名') age = forms.CharField(label='年龄') email = forms.CharField(label='邮箱') class RegisterForm(forms.ModelForm): class Meta: # 1 指定关联的Model是谁 model = Author # 2 指定生成控件的字段们 fields = "__all__" # 3 指定每个控件对应的label labels={ "name":"用户名称", "age":"用户年龄", "email":"用户邮箱", "isactive":"是否激活" } class WigetForml(forms.Form): uname = forms.CharField(label='用户名称') upwd = forms.CharField(label='用户密码',widget=forms.PasswordInput) class WigetForms1(forms.Form): uname = forms.CharField( label="用户名称", widget=forms.TextInput( attrs={ "class":"form_", "id":"uname" } ) ) upwd = forms.CharField( label='用户密码', widget=forms.PasswordInput( attrs={ "class":"upwd", "id":"password" } ) ) class WidegetForm2(forms.ModelForm): class Meta: model =Author fields = ['name','age','email'] labels={"name":"姓名", "age":"邮箱", "email":"电子邮箱",} widgets={ "age":forms.NumberInput(attrs={'placeholder':"年龄","id":"age"}), "email":forms.EmailInput() } cookies 和 session 1 cookies 1 django 中使用 cookies 1 设置 cookis的值(将数据保存到客户端) 语法: 响应对象 .set_cookie(key,value,expires) key:cookie的名字 expires:保存时间,以s为单位 1 不使用模板 resp = HTTPResponse('响应给客户端的一句话') resp.set_cookie(key,value,expires) return resp 2 使用模板 resp = render(request,'xxx.html',locals()) resp.set_cookie(key,value,expires) return resp 4 使用重定向 resp = redirect('/地址/') resp.set_cookie(key,value,expires) return resp 2 获取cookies的值 伴随着请求对象到达服务器之后再获取cookie的值 request.COOKIES:封装了当前访问站点下的所有的cookie的信息 3 删除cookie的值 通过响应对象通知客户端删除数据 resp.delete_cookie(key) 2 session (默认存10个月 ) 1 设置session的值 request.session['key']=值 2 获取session的值 value = request.session['key'] value = request.get('key') 3 删除 session的值 del request.session['key'] 4 有关session的配置 在 settings.py中,有关session的设置 1 SESSION_COOKIE_AGE 作用:设置sessionID在cookie中的存活时间 ex: SESSION_COOKIE_AGE=60*30 [30分钟] 2 SESSION_EXPIRE_AT_BROWSER_CLOSE 作用:设置浏览器关闭时则清除服务器上对应的session空间 ex: SESSION_EXPIRE_AT_BROWSER_CLOSE = True 1 DJango中的ajax处理 1 django 处理JSON 1 django中的查询结果集处理 使用django提供的序列化的类来完成querySet到json字符串的转换 from django.core import serializers serializers.serialize('json',QuerySet) 1 serialize()只能将查询结果集转换成json,单个对象则不可以 2 如果使用serialize的话,可以把get换成filter 2 提交POST请求 1 网页中任意一个位置增加{% csrf_token%} 目的:是为了得到csrf令牌(隐藏域)的键和值 2 在ajax post请求中得奖参数时,需要将csrf令牌的键和值也提交给服务器
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = '0_!2t5p3rpzl$y-jp$*^gh=gqxj=hb8paz()z&dvrwjnl--*^d' # SECURITY WARNING: don't 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', 'api', ] 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 = 'drum.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 = 'drum.wsgi.application' # Database # https://docs.djangoproject.com/en/1.11/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'drum', 'USER':'root', 'PASSWORD': '密码', 'HOST':'127.0.0.1', 'PORT': 3306, } } 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/1.11/topics/i18n/ LANGUAGE_CODE = 'zh-Hans' TIME_ZONE = 'Asia/Shanghai' USE_I18N = True USE_L10N = True USE_TZ = False STATICFILES_DIRS=(os.path.join(BASE_DIR,'static'),) STATIC_URL = '/static/'
#建立关于项目的环境 #Virtualenv XXXenv #引用环境 #Source stockenv/bin/activate #成功 #(XXXenv root:)
python -m venv 环境名
------------------------------
# 引用django内部数据 from django.contrib.auth.models import AbstractUser
AUTH_USER_MODEL = 'APP/Userinfo'
'应用/model类'
# 告诉Django项目用哪个APP下的哪儿张表做认证
AUTH_USER_MODEL = 'APP名称.UserInfo'
------------------------------
小数位
models.DecimalField(max_digits=8,decimal_places=2)
8位数,2位小数点
------------------------------
重点6
同一张表 共同foreikey 一张表 一对多的关系
需要添加related_name = '名字随便取'
需要添加related_name = '名字随便取'
------------------------------
from django.contrib.auth.hashers import make_paaword,chec_password
make_password (1,2,3)
第一个参数:要加密的字符串
第二个参数:NOne,不能不写,当指定参数一定,每次加密密码都会相同,否则不同
第三个参数:加密方式
check_password(明文,密文)
返回值 :True False 用来验证密码
------------------------------
from django.contrib.auth import login,logout,authenticate
if user is not None and user.is_active:
login(request,user)
------------------------------
from django.db import connection
cursor = connection.cursor() # 数据库连接对象,使用原生sql时使用
____________________________
多对多中,可以使用唯一约束
在class Meata:
unique_together=(('表1','表2'),)