学习课程 django1.11.7

1.CS/BS简介

1.1 概念:
BS:B browser 浏览器   S server  服务器   主流
CS:C client  客户端   S server  服务器
B/S结构是WEB兴起后的一种网络结构模式,WEB浏览器是客户端最主要的应用软件。这种模式统一了客户端,将系统功能实现的核心部分集中到服务器上,简化了系统的开发、维护和使用。
eg:
CS = Client - Server = 客戶端 - 服务器。
例子: QQ,迅雷,快播,暴風影音,各种网络游戏等等。BS = Browser - Server = 浏览器 - 服务器。
例子:所有的网站都是BS结构。( 知乎 / 果壳 / 微博 / 等等等等等等 )
1.2 CS/BS区别:
1、开发维护成本cs开发维护成本高于bs。因为采用cs结构时,对于不同的客户端要开发不同的程序,而且软件安装调试和升级都需要在所有客户机上进行。bs只需要将服务器上的软件版本升级,然后从新登录就可以了。
2、客户端负载cs客户端负载大。cs客户端不仅负责和用户的交互,收集用户信息,而且还需要通过网络向服务器发出请求。bs把事务处理逻辑部分交给了服务器,客户端只是负责显示。
3、安全性cs安全性高。cs适用于专人使用的系统,可以通过严格的管理派发软件。bs使用人数多,不固定,安全性低。
4、作用范围Client/Server是建立在局域网的基础上的。Browser/Server是建立在广域网的基础上的。
1.3 CS/BS应用语言:
CS/BS客户端和服务器的交互模型Client客户端Browser浏览器ServerWeb后端pythondjango     7flask      2javastruts2/struts1hibernatespringspringmvcmybatisspringbootspringcludephpyiicithinkphp

2.MVC

MVC:软件架构思想简介:MVC开始是存在于桌面程序中的,M是指业务模型 model,V是指用户界面 view,C则是控制器 controler,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据可以分别用柱状图、饼状图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新
实现了模型层的复用核心思想: 解耦合Model模型封装数据的交互操作CRUDView视图是用来将数据呈现给用户的Controller控制器接受用户输入输出用来协调Model和View的关系,并对数据进行操作,筛选流程控制器接受用户请求调用模型,获取数据控制器将数据展示到视图中

3.MTV

MTV也叫做MVT本质上就是MVC,变种Model同MVC中ModelTemplate模板只是一个html,充当的是MVC中View的角色,用来做数据展示Views视图函数相当于MVC中Controller

4.Django

4.1 简介
Django是一个开放源代码的Web应用框架,它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统)软件。并于2005年7月在BSD许可证下发布。这套框架是以比利时的吉普赛爵士吉他手Django Reinhardt来命名的。重量级的框架,替开发者想了太多的事情,帮开发者做了很多的选择,内置了很多的功能
官方网站http://www.djangoproject.com
使用版本1.11.7LTS:长期支持版本以后再学2.2 LTS
4.2 虚拟环境
虚拟环境mkvirtualenv --python=/usr/bin/python3 django200x创建虚拟环境deactivate退出虚拟环境workon进入虚拟环境rmvirtualenv删除虚拟环境
4.3 虚拟化技术
虚拟化技术(1)虚拟机      (2)虚拟容器Docker  支持很多种语言(3)虚拟环境--迷你python专用将python依赖隔离
4.4 安装
 pip install djangopip install django==1.11.7   一定要使用==pip install django==1.11.7 -i https://pypi.douban.com/simple  豆瓣源查看django是否安装成功pip freezepip list进入python环境import djangodjango.get_version()
4.5 创建django项目
django-admin startproject 项目名字注意:项目的名字不能以数字开头tree命令观察项目结构如果未安装   yum install tree
项目结构项目名字manage.py管理整个项目的文件以后的命令基本都通过他来调用项目名字__init__python包而不是一个文件夹settings项目全局配置文件ALLOWED_HOST=["*"]修改settingsLANGUAGE_CODE='zh-hans'TIME_ZONE='Asia/Shanghai'urls根路由url(p1,p2)wsgi用在以后项目部署上,前期用不到服务器网关接口webserver gateway interface
启动项目python manage.py runserver使用开发者服务器启动项目默认会运行在本机的 8000端口上启动服务器命令(1)python manage.py runserver(2)python manage.py runserver 9000(3)python manage.py runserver 0.0.0.0:9000
创建一个应用python manage.py startapp App/django-admin startapp AppApp结构__init__views视图函数视图函数种参数是request  方法的返回值类型是HttpResponsemodels模型admin后台管理apps应用配置tests单元测试migrations__init__迁移目录
4.6 拆分路由器
 python manager.py startapp  TwoTwo下创建urlsurlpatterns = [url(r'^index/',views.index)]创建views方法主路由引用url(r'^two/',include('Two.urls')),访问url127.0.0.1:8000/two/index/
4.7 编写第一个请求
1.编写一个路由url(p1, p2)url(r'^index/',views.index),p1 正则匹配规则p2 对应的视图函数的路径
2.编写视图函数(1)本质上还是一个函数def index(request):return HttpResponse('123')要求:只是默认第一个参数是一个request,必须返回一个HttpResponse(2)返回值:1.HttpResponse()HttpResponse('123')HttpResponse('<h1>123</h1>')2.render在App下创建templates注意名字是固定的,不能打错单词render方法的返回值类型也是一个HttpResponse类型的要求:将应用注册到项目的settings中INSTALLED_APPS中加载路由的方式INSTALLED_APPS---》‘Two’INSTALLED_APPS---》‘Two.apps.TwoConfig’  版本限制 1.9之后才能使用
3.模板配置有两种情况①在App中进行模板配置- 只需在App的根目录创建templates文件夹即可- 必须在INSTALLED_APP下安装app ②在项目目录中进行模板配置- 需要在项目目录中创建templates文件夹并标记- 需要在settings中进行注册  settings--》TEMPLATES--》DIRS-                                                                        os.path.join(BASE_DIR,'templates')注意:开发中常用项目目录下的模板    理由:模板可以继承,复用
# ext
Django
3周1 django的基础(1)django的基本流程(2)M    model(3)T     template(4)V     views(5)cookie session(6)模型的高级   一对一  一对多  多对多(7)边边角角的东西
2 项目 全栈的项目电商
3 前后端分离
============================================1 创建django项目django-admin startproject 项目的名字项目的名字不能以数字开头可以通过tree命令来查看目录结构如果没有tree  可以通过yum install tree来安装启动服务器的命令是python manage.py runserver如果报错了widgets.py的151行错误  那么就要进入到
虚拟环境下 然后将151行的代码中的逗号删除就可以了2 启动服务器的命令是python manage.py runserver
默认的端口号是80  默认访问的主机地址是127.0.0.1就是本地
需要在阿里云开启入方向和出方向的端口 注意要重启服务器3 如果访问的时候报错 ALLOWED_HOSTS 那么是因为django的项目
需要在settings中设置ALLOWED_HOSTS的值  一般情况下可以设置
ALLOWED_HOSTS的值*4 设置django的欢迎页面是中文在settings中设置LANGUAGE_CODE = 'zh-hans'5 django启动服务器的指令是python manage.py runserver 0.0.0.0:8000django的服务器会检测你代码修改 自动重新部署6 django默认的时间是英国时间 修改默认时区是在settings中
TIME_ZONE = 'Asia/Shanghai'7 flask的路由+视图@blue.route('/index/')def index():return 'index'django中其实际上就是将路由和视图函数分开了在urls中定义路由r'^index/访问的路由views.index 是视图函数的路径url(r'^index/',views.index)在项目下创建一个views的文件  然后在文件中定义视图函数视图函数必须传递一个参数就是request  视图函数的返回值类型必须是HttpResponse8 一个项目中的请求是有很多的  那么所有的路由都写在一个urls和一个views中吗答 不可以  因为如果所有的逻辑都写一个py文件  那么后期的维护就不是很好(1)创建App文件夹  django-admin startapp  App(2)创建一个urls的python文件(3)在根路由/主路由(项目下的urls)引入子路由的urls(App下的urls)url(r'^app/',include('App.urls'))(4)在子路由中定义urlpatterns的列表  注意名字必须是urlpatterns(5)在urlpattersn中定义路由url(r'^index4/',views.index4)(6)在views中定义视图函数(7)访问:127.0.0.0:8000/app/index49 创建app有2种方式(1)django-admin startapp App(2)python manage.py startapp App10 测试的是视图函数返回一个页面(模板)(1)在外层的项目下创建一个文件夹叫做templates(2) 视图函数的返回值是render(request,'testRender.html')(3) 如果模板是在项目下的  那么需要在settings中配置TEMPLATES下的DIRS中os.path.join(BASE_DIR,'templates')11 模板在App下(1)在App中创建templates的文件夹(2)视图函数的返回值是render(request,'testRender.html')(3)在settings中的INSTALLED_APPS中添加'Two'  (app的名字)
4.8 Django的工作机制
1.用manage.py runserver 启动Django服务器时就载入了在同一目录下的settings .py。该文件包含了项目中的配置信息,如URLConf等,其中最重要的配置就是ROOT_URLCONF,它告诉Django哪个Python模块应该用作本站的URLConf,默认的是urls.py2.当访问url的时候,Django会根据ROOT_URLCONF的设置来装载URLConf。3.然后按顺序逐个匹配URLConf里的URLpatterns。如果找到则会调用相关联的视图函数,并把HttpRequest对象作为第一个参数(通常是request)4.最后该view函数负责返回一个HttpResponse对象。

5.模板显示

显示在模板中先挖坑{{ var }}再填坑渲染模板的时候传递上下文进来上下文是一个字典context={'key':'value'}模板的兼容性很强不传入不会报错多传入也会自动优化掉浏览器不认模板浏览器也叫做html解析器  只识别html文件在到达浏览器之前,已经进行了转换,将模板语言转换成了HTMLfor 支持{% for %}render底层实现:应用场景,发送邮件,邮件的内容需要使用render方法来操纵加载three_index = loader.get_template('three.html')content={'xxx':'xxxx'}渲染result = three_index.render(content=content)return HttpResponse(result)

6.修改数据库

在settings中的DATABASES中进行修改
实际上都是关系型数据库
mysql'ENGINE': 'django.db.backends.mysql',NAME数据库名字USER用户名字PASSWORD密码HOST主机PORT端口号引号加不加“”都可以
mysql迁移---》有坑---驱动问题
mysql驱动mysqlclient- python2,3都能直接使用- 致命缺点- 对mysql安装有要求,必须指定位置存在配置文件mysql-python- python2 支持很好- python3 不支持pymysql会伪装成mysqlclient和mysql-python- python2,python3都支持init中   import  pymysql      pymysql.install_as_MySQLdb()

7.DML

1 #django默认提供的13张表 可以直接使用python manage.py migrate#如果我们自定义模型 先要生成迁移文件 python manage.py makemigrations执行迁移文件 python manage.py migrate# 如果模型想被迁移,那么模型所在的App 必须要在settings的INSTALLED_APPS去加载数据操作迁移生成迁移python manage.py makemigrations执行迁移python manage.py migrate才会真正在数据库产生表ORMObject Relational Mapping 对象关系映射将业务逻辑和sql进行了一个解耦合通过models定义实现  数据库表的定义模型定义(1)继承models.Model(2)会自动添加主键列(3)必须指定字符串类型属性的长度class Student(models.Model):name = modes.CharField(max_length=16)age = models.IntegerField(default=1)存储数据创建对象进行save()数据查询模型.objects.all()模型.objects.get(pk=2)更新基于查询save()删除基于查询delete()

8.django shell

python manage.py shelldjango 终端python manager.py shell集成了django环境的python 终端通常用来调试eg:from Two.models import Studentstudents = Student.objects.all()for student in students:print(students.name)

9.数据级联-一对多

一对多模型关系:class Grade(models.Model):g_name = models.CharField(max_length=32)class Student(models.Model):s_name =models.CharField(max_length=16)s_grade=models.ForeignKey(Grade) 案例:(1).多方获取一方,根据学生找班级名字显性属性:就是你可以在中直接观察到的属性---》通过多方获取一方  那么可以使用多方调用显性属性直接获取一方数据student = Student.objects.get(pk=2)grade = student.s_gradereturn HttpResponse(grade.g_name)(2).一方获取多方,根据班级  找所有的学生隐性属性:就是我们在类中观察不到的,但是可以使用的属性---》通过一方获取多方 那么可以使用一方数据的隐性属性 获取多方数据# 如果是一对多 一方是主表,2方是主表# django可以使用2方的对象调用多方模型的小写_set 就可以获取多方所有数据结构grade = Grade.objects.get(pk=2)students = grade.student_set.all()content = {'students':students}return render(request,'students_list.html',content)

10.元信息

字段类型:CharField,TextField,IntegerField,FloatField,BooleanField,DecimalField,NullBooleanrField,AutoField,FileField,ImageField,DatetimeFiled
字段约束:max_length,default,unique,index,primary_key,db_column
# ext
3 django中模型的字段类型以及约束
定义属性概述·django根据属性的类型确定以下信息·当前选择的数据库支持字段的类型·渲染管理表单时使用的默认html控件·在管理站点最低限度的验证·django会为表增加自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后,则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·blank·如果为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

11.模型过滤(查询)

Django默认通过模型的objects对象实现模型数据查询。
Django有两种过滤器用于筛选记录: 这两者都是querysetfilter:  返回符合筛选条件的数据集exclude    :返回不符合筛选条件的数据集
链式调用:多个filter和exclude可以连接在一起查询Person.objects.filter().filter().xxxx.exclude().exclude().yyyyPerson.objects.filter(p_age__gt=50).filter(p_age__lt=80)注意数据类型Person.objects.exclude(p_age__gt=50)Person.objects.filter(p_age__in=[50,60,61])

12.创建对象的方式

创建对象的方式(1)创建对象1   常用person = Person()   person.p_name='zs'  person.p_age=18(2)创建对象2直接实例化对象,设置属性创建对象,传入属性使用person =  Model.objects.create(p_name='zs',p_age=18)person.save()自己封装类方法创建在Manager中封装方法创建(3)创建对象3person = Person(p_age=18)(4)创建对象4注意:__init__已经在父类models.Model中使用,在自定义的模型中无法使用在模型类中增加类方法去创建对象@classmethod  def create(cls,p_name,p_age=100):return cls(p_name=p_name,p_age=p_age)person = Person.create('zs')

13.查询集

概念:查询集表示从数据库获取的对象集合,查询集可以有多个过滤器。(6个)
过滤器:过滤器就是一个函数,基于所给的参数限制查询集结果,返回查询集的方法称为过滤器。查询经过过滤器筛选后返回新的查询集,所以可以写成链式调用。获取查询结果集  QuerySet 是一个集合,是可以遍历的all模型.objects.all()    #QuerySet 是一个集合,是可以遍历filter模型.objects.filter()  #QuerySet 是一个集合,是可以遍历exclude模型.objects.exclude()  #QuerySet 是一个集合,是可以遍历order_bypersons= Person.objects.order_by('id')   #QuerySet 是一个集合,是可以遍历默认是根据id排序注意要写的是模型的属性values##QuerySet t [{'id': 5, 'name': 'h5', 'num': 1}, ]persons= Person.objects.order_by('id') persons.values()注意方法的返回值类型   切片限制查询集,可以使用下标的方法进行限制左闭右开区间不支持负数下标没有负数实际上相当于 limit  offsetstudentList = Student.objects.all()[0:5]  #QuerySet 是一个集合,是可以遍历第一个参数是offset  第二个参数是limit缓存集/懒查询/查询集的缓存:每个查询集都包含一个缓存,来最小化对数据库的访问在新建的查询集中,缓存首次为空,第一次对查询集求值,会发生数据缓存,django会将查询出来的数据做  一个缓存,并返回查询结果,以后的查询直接使用查询集的缓存。- 都不会真正的去查询数据库- 懒查询/懒加载- 只有我们在迭代结果集,或者获取单个对象属性的时候,它才会去查询数据- 为了优化我们结果和查询
获取单个对象:get不存在会抛异常  DoesNotExist存在多于一个 MultipleObjectsReturned使用这个函数 记得捕获异常last#<class 'App.models.Grade'>返回查询集种的最后一个对象first#<class 'App.models.Grade'>需要主动进行排序persons=Person.objects.all().first()内置函数:框架自己封装得方法 帮助我们来处理业务逻辑如果值不存在 #则返货queryset的空列表if 字段.count() >0:返回当前查询集中的对象个数eg:登陆if exists: 如果有返回True  如果没有返回False判断查询集中是否有数据,如果有数据返回True没有反之
字段查询:对sql中where的实现,作为方法filter(),exclude(),get()的参数语法:属性名称__比较运算符=值Person.objects.filter(p_age__gt=18)条件属性__操作符=临界值gtgreat thangtegreat than equalsltless thanlteless than equalsgt,gte,lt,lte:大于,大于等于,小于小于等于filter(sage__gt=30)inin:是否包含在范围内,filter(pk__in=[2,4,6,8])单引号可以使用startswtith类似于 模糊查询 like# grade_list = Grade.objects.filter(name__startswith='p')# grade_list = Grade.objects.filter(num__startswith=1)endswith以 xx 结束  也是likecontainscontains:是否包含,大小写敏感,filter(sname__contains='赵')isnull,isnotnull#django模型都是notnull. 但是我们将来会设置某些字段可以为Nullisnull,isnotnull:是否为空,filter(sname__isnull=False)
时间models.DateTimeField(auto_now_add=True)  # 第一次时间 创建的时间yearmonth 会出现时区问题  需要在settings中的USE-TZ中设置为 Falsedayweek_dayhourminutesecondorders = Order.objects.filter(o_time__month=9)有坑:时区问题关闭django中自定义的时区USE-TZ=False在数据库中创建对应的时区表
注意:mysql oracle中所说的聚合函数 多行函数  组函数 都是一个东西  max min avg sum count
聚合函数/组函数/多行函数/高级函数模型:class Customer(models.Model):c_name = models.CharField(max_length=16)c_cost = models.IntegerField(default=10)使用:使用aggregate()函数返回聚合函数的值Avg:平均值Count:数量     Max:最大#{'c_cost__min': 1}Min:最小Sum:求和eg:Student.objects.aggregate(Max('age'))
跨关系查询: # 查谁 谁调用模型:class Grade(models.Model):g_name = models.CharField(max_length=16)class Student(models.Model):s_name = models.CharField(max_length=16)s_grade = models.ForeignKey(Grade)使用:模型类名__属性名__比较运算符,实际上就是处理的数据库中的joinGrade  ---g_name      Student---》s_name  s_grade(外键)gf = Student.objects.filter(s_name='凤姐')print(gf[0].s_grade.name)grades = Grade.objects.filter(student__s_name='Jack')查询jack所在的班级
F对象 eg:常适用于表内属性的值的比较模型:class Company(models.Model):c_name = models.CharField(max_length=16)c_gril_num = models.IntegerField(default=5)c_boy_num = models.IntegerField(default=3)F:获取字段信息,通常用在模型的自我属性比较,支持算术运算eg:男生比女生少的公司companies = Company.objects.filter(c_boy_num__lt=F('c_gril_num'))eg:女生比男生多15个人companies = Company.objects.filter(c_boy_num__lt=F('c_gril_num')-15)
Q对象 eg:常适用于逻辑运算 与或或 非年龄小于25:Student.objects.filter(Q(sage__lt=25))eg:男生人数多余5 女生人数多于10个:companies = Company.objects.filter(c_boy_num__gt=1).filter(c_gril_num__gt=5)companies = Company.objects.filter(Q(c_boy_num__gt=5)|Q(c_gril_num__gt=10))支持逻辑运算:与或非&|~年龄大于等于的:Student.objects.filter(~Q(sage__lt=25))

14.Template概念

概念:模板在Django框架中,模板是可以帮助开发者快速生成,呈现给用户页面的工具模板的设计方式实现了我们MVT中VT的解耦,VT有着N:M的关系,一个V可以调用任意T,一个T可以供任意V使用模板处理分为两个过程加载渲染模板中的动态代码段除了做基本的静态填充,可以实现一些基本的运算,转换和逻辑早期的web服务器  只能处理静态资源请求  模板能处理动态资源请求 依据计算能生成相应的页面注意:在Django中使用的就是Django模板,在flask种使用得是jinja2模板
模板组成:模板主要有2个部分① HTML静态代码② 动态插入的代码段(挖坑,填坑)

15.模板语法:

(1)变量
变量视图传递给模板的数据获取视图函数传递的数据使用{{ var }}接收遵守标识符规则:拒绝关键字 保留字 数字。。。如果变量不存在,则插入空字符串来源:视图中传递过来的标签中,逻辑创建出来的
(2)模板中的点语法
模版中的点语法属性或者方法student.name/student.getnameclass Student(models.Model):s_name = models.CharField(max_length=16)def get_name(self):return self.s_name弊端:模板中的小弊端,调用对象的方法,不能传递参数 为什么不能传递参数  因为连括号都没有索引 students.0.gname字典  student_dict.hobby
(3)标签
特征:标签分为单标签和双标签双标签必须闭合
功能标签:(for)forfor i in xxxempty{% empty %}判断之前的代码有没有数据 如果没有,显示empty下面的代码(语句2)eg:{% for 变量 in 列表 %}语句1 {% empty %}语句2{% endfor %}forloop循环状态的记录{{ forloop.counter }} 表示当前是第几次循环,从1数数{{ forloop.counter0}}表示当前是第几次循环,从0数数{{ forloop.revcounter}}表示当前是第几次循环,倒着数数,到1停{{ forloop.revcounter0}}表示当前第几次循环,倒着数,到0停{{ forloop.first }} 是否是第一个  布尔值{{ forloop.last }} 是否是最后一个 布尔值
功能标签:(if)if分支判断if - elseif - elif -else
注释:单行注释{#  被注释掉的内容  #}多行注释{% comment %}内容{% endcomment %}
withratio乘{% widthratio 数  分母  分子  %}{% widthratio count 1 5 %}
整除:{% if num|divisibleby:2 %}整除{% if forloop.counter|divisibleby:2%}奇偶行变色
 ifequal: ifequal{%  ifequal  value1 value2 %}语句{% endifequal %}{% ifequal forloop.counter 5 %}
(4) 过滤器
 |将前面的输入作为后面的输出add:<h4>{{ count|add:2 }}</h4><h4>{{ count|add:-2 }}</h4>upper:lower:safe确认安装进行渲染eg:code = """<h2>睡着了</h2><script type="text/javascript">var lis = document.getElementsByTagName("li");for (var i=0; i< lis.length; i++){var li = lis[i];li.innerHTML="日本是中国领土的一部分!";}</script>"""endautoescape:{% autoescape off%}code{% endautoescape %}
(5)结构标签
结构标签block块坑用来规划页面布局,填充页面首次出现代表规划第二次c出现代表填坑第三次出现也代表填坑,默认会覆盖第N次...如果不想被覆盖  {{block.super}}extends继承面向对象的体现提高模板的复用率include包含将其它模板作为一部分,包裹到我们的页面中
(6)加载静态资源
加载静态资源static--》 html  css js  img font静态资源路径 /static/css/xxx.css不推荐硬编码需要在settings中添加  STATICFILES_DIRS=[os.path.join(BASE_DIR,'static')]推荐{% load static%}{%static,'css/xxx.css'%}思考:html和模板中的页面  都可以使用load吗?  注意必须在模板中使用坑点:仅在DEBUG模式下可以使用  如果settings中的DEBUG=False 那么是不可以使用的

16.常见的请求状态码

请求状态码2xx成功3xx重定向 302  301 永久重定向4xx客户端错误5xx服务端错误200  成功   301  永久重定向  302 重定向  403 防止跨站攻击  404 路径  405  请求方式  500 业务逻辑错误

17.view视图函数

1.概念及基础语法
概念:视图函数是MTV中的View,相当于MVC中的Controller作用,控制器 接收用户输入(请求),协调模板模型,对数据进行处理,负责的模型和模板的数据交互。视图函数返回值类型:(1)以Json数据形势返回前后端分离return  JsonResponse(2)以网页的形势返回    HttpResponse   render   redirect重定向到另一个网页错误视图(40X,50X)
url匹配正则注意事项:  正则匹配时从上到下进行遍历,匹配到就不会继续向后查找了匹配的正则前方不需要加反斜线正则前需要加 (r)表示字符串不转义
url匹配规则:按照书写顺序,从上到下匹配,没有最优匹配的概念,匹配到就停止了         eg:hehe/hehehe
url接受参数:(1)如果需要从url中获取一个值,需要对正则加小括号url(r'^grade/(\d+)$',views.getStudents),注意,url匹配中添加了 () 取参,在请求调用的函数中必须接收 def  getStudents(request,classId):一个参数(2)如果需要获取url路径中的多个参数,那就添加多个括号,默认按照顺序匹配路径名字url(r'^news/(\d{4})/(\d+)/(\d+)$',views.getNews),匹配年月日 def getNews(request,year,month,day):多个参数eg:def get_time(request,hour, minute, second):return HttpResponse("Time %s: %s: %s" %(hour, minute, second))(3)参数也可以使用关键字参数形势url(r'^news/(?P<year>\d{4})/(?P<month>\d)+/(?P<day>\d+)$',views.getNews),多个参数并且指定位置eg:def get_date(request,  month, day, year):return HttpResponse("Date %s- %s- %s" %(year, month, day))总结路径参数:位置参数eg:127.0.0.1:8000/vie/testRoute/1/2/3/r('^testRoute/(\d+)/(\d+)/(\d+)/')使用圆括号包含规则一个圆括号代表一个参数代表视图函数上的一个参数参数个数和视图函数上的参数一一对应(除默认request)关键字参数可以在圆括号指定参数名字 (?P<name>reg)视图函数中存在和圆括号中name对应的参数参数不区分顺序个数也需要保持一致,一一对应
2.内置函数
内置函数locals()将局部变量,使用字典的形式打包key是变量的名字value是变量的值
3.反向解析
# ext
#     反向解析 作用:获取请求路径
#          反向解析的基本使用
#                 (1)在跟路由中设置namespace属性
#                 (2)在子路由中设置name属性
#                 (3)reverse('app:index')
反向解析反向解析的用处:获取请求资源路径,避免硬编码。配置(1)在根urls中url(r'^views/', include('ViewsLearn.urls',namespace='view')),在根路由中的inclue方法中添加namespace参数(2)在子urls中url(r'^hello/(\d+)',views.hello,name='sayhello'),在子路由中添加name参数(3)在模板中使用<a href="{% url 'view:sayhello' %}">Hello</a>调用的时候 反向解析的路径不能有编译错误  格式是  {% url 'namespace:name%}'在视图函数中使用reverse('view:sayhello')格式:reverse('namespace:name')           如果存在位置参数{% url  ‘namespace:name'   value1 value2 ... %}如果存在关键字参数{% url 'namespace:name'   key1=value1 key2=vaue2 ...%}在模板中使用<a href="{% url 'view:sayhello'  year=2017 %}">Hello</a>优点如果在视图,模板中使用硬编码连接,在url配置发生改变时,需要变更的代码会非常多,这样导致我们的代码结构不是很容易维护,使用反向解析可以提高我们代码的扩展性和可维护性。

18.request对象

概念:django框架根据Http请求报文自动生成的一个对象,包含了请求各种信息。
属性:path:请求的完整路径method:GET  1.11版本最大数据量2KPOST 参数存在请求体中,文件上传等。请求的方法,常用GET,POST应用场景:前后端分离的底层 判断请求方式 执行对应的业务逻辑GET:QueryDict类字典结构 key-value一个key可以对应多个值get 获取最后一个getlist 获取多个类似字典的参数,包含了get请求方式的所有参数POST: 类似字典的参数,包含了post请求方式的所有参数面试题:QueryDict和Dict的区别?dict是字典对象,没有urlencode()方法;QueryDict对象,有urlencode()方法,作用是将QueryDict对象转换为url字符串;一般QueryDict通过params = copy.deepcopy(request.GET)得到的,这时params是QueryDict对象;也能params[key]=value进行添加数据encoding:编码方式,常用utf-8 # 请求头 服务器响应之后有乱码问题FILES:类似字典的参数,包含了上传的文件  文件上传的时候会使用  页面请求方式必须是post   form的属性enctype=multipart/form-dataflask和django通用的   一个是专属于djangoCOOKIES:类似字典的参数,包含了上传的文件  获取cookiesession:类似字典,表示会话META:   应用反爬虫  REMOTE_ADDR  拉入黑名单客户端的所有信息 ipprint(request.META)for key in request.META:print(key, request.META.get(key))print("Remote IP", request.META.get("REMOTE_ADDR"))

19.HttpResponse对象

当浏览器访问服务器的时候 那么服务器响应的数据类型

响应分类:(1)HTML响应 (2)JsonResponse(前后端分离)
HTML响应
(1)基类HttpResponse   不使用模板,直接HttpResponse()def hello(request):response = HttpResponse()response.content = "德玛西亚"response.status_code = 404response.write("千锋")response.flush()return response方法init               初始化内容write(xxx)         直接写出文本flush()               冲刷缓冲区set_cookie(key,value='xxx',max_age=None,exprise=None)delete_cookie(key)       删除cookie,上面那个是设置(2)render转发:方法的返回值类型也是一个HttpResponse(3)HttpResponseRedirect重定向HttpResponse的子类,响应重定向:可以实现服务器内部跳转return HttpResponseRedict('/grade/2017')使用的时候推荐使用反向解析状态码:302简写方式:简写redirect方法的返回值类型就是HttpResponseRedirect反向解析:(1)页面中的反向解析 url方法基本使用{% url 'namespance:name'%}url 位置参数{% url 'namespace:name'  value1 value2 %}url关键字参数{% url 'namespace:name' key1=value1 key2 = value2 %}(2)python代码中的反向解析(一般python代码的反向解析都会结合重定向一起使用)基本使用reverse('namespace:name')位置参数reverse('namespace:name', args=(value1, value2 ...))reverse('namespace:name', args=[value1, value2 ...])关键字参数reverse('namespace:name', kwargs={key1:value2, key2:value2 ...})

JsonResponse

#ext
django的语法中是不能直接返回data的
JsonResponse 缺点:1 中文乱码    2(默认的视图函数)序列化难
这个类是HttpRespon的子类,它主要和父类的区别在于:
1.它的默认Content-Type 被设置为: application/json2.第一个参数,data应该是一个字典类型,当 safe 这个参数被设置为:False ,那data可以填入任何能被转换为JSON格式的对象,比如list, tuple, set。 默认的safe 参数是 True. 如果你传入的data数据类型不是字典类型,那么它就会抛出 TypeError的异常。def get_info(request):data = {"status": 200,"msg": "ok",}return JsonResponse(data=data)

HttpResponse子类

HttpResponse子类HttpResponseRedirect -302HttpResponsePermanentRedirect- 重定向,永久性- -301HttpResponseBadRequest -400  请求对象有问题HttpResponseNotFound- 404   路径错误HttpResponseForbidden- 403   csrf 防跨站攻击 HttpResponseNotAllowed- 405   请求方式不允许HttpResponseServerError- 500   后端逻辑错误Http404- Exception- raise 主动抛异常出来

20.会话技术

为什么会有会话技术?服务器如何识别客户端Http在Web开发中基本都是短连接请求生命周期从Request开始,到Response就结束
会话技术:cookie session  token(自定义的session)
(1)cookie
 客户端会话技术,数据都存储在客户端,以key-value进行存储,支持过期时间max_age,默认请求会携带本网站的所有cookie,cookie不能跨域名,不能跨浏览器,cookie默认不支持中文,base64cookie是服务器端创建  保存在浏览器端设置cookie应该是服务器 response获取cookie应该在浏览器 request删除cookie应该在服务器 responsecookie使用:设置cookie:response.set_cookie(key,value)获取cookie:username =request.COOKIES.get("username")删除cookie:response.delete_cookie("username")可以加盐:加密 获取的时候需要解密加密  response.set_signed_cookie('name', name, salt="xxxx")解密  获取的是加盐之后的数据uname = request.COOKIES.get('content)获取的是解密之后数据uname = request.get_signed_cookie("content", salt="xxxx")通过Response将cookie写到浏览器上,下一次访问,浏览器会根据不同的规则携带cookie过来max_age:整数,指定cookie过期时间  单位秒expries:整数,指定过期时间,还支持是一个datetime或   timedelta,可以指定一个具体日期时间max_age和expries两个选一个指定过期时间的几个关键时间max_age 设置为 0 浏览器关闭失效设置为None永不过期expires=timedelta(days=10) 10天后过期
(2)session
 服务端会话技术,数据都存储在服务端,默认存在内存 RAM,在django被持久化到了数据库中,该表叫做Django_session,这个表中有三个字段,分别为seesion_key,session_data,expris_date.Django中Session的默认过期时间是14天,支持过期,主键是字符串,默认做了数据安全,使用了BASE64- 使用的base64之后 那么这个字符串会在最后面添加一个==- 在前部添加了一个混淆串依赖于cookies
session使用:设置sessionrequest.session["username"] = username获取sessionusername = request.session.get("username")使用session退出del request.session['username']cookie是脏数据response.delete_cookie('sessionid')session是脏数据request.session.flush()冲刷session常用操作get(key,default=None) 根据键获取会话的值clear() 清楚所有会话flush() 删除当前的会话数据并删除会话的cookiedelete request['session_id'] 删除会话session.session_key获取session的keyrequest.session[‘user’] = username数据存储到数据库中会进行编码使用的是Base64
(3)token
基本概念:Token 的中文意思是“令牌”。主要用来身份验证。 Facebook,Twitter,Google+,Github 等大型网站都在使用。比起传统的身份验证方法,Token 有扩展性强,安全性高的特点,非常适合用在 Web 应用或者移动应用上,如果使用在移动端或客户端开发中,通常以Json形式传输,服务端会话技术,自定义的Session,给他一个不能重复的字符串,数据存储在服务器中
验证方法:使用基于 Token的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:
1.客户端使用用户名跟密码请求登录
2.服务端收到请求,去验证用户名与密码
3.验证成功后,服务端会签发一个 Token,再把这个Token 发送给客户端
4.客户端收到 Token以后可以把它存储起来,比如放在 Cookie里或者 Local Storage里
5.客户端每次向服务端请求资源的时候需要带着服务端签发的Token
6.服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
python常用Token生成方法:
(1)binascii.b2a_base64(os.urandom(24))[:-1]使用举例:>>> import binascii>>> import os>>>binascii.b2a_base64(os.urandom(24))[:-1]b'J1pJPotQJb6Ld+yBKDq8bqcJ71wXw+Xd'总结:这种算法的优点是性能快, 缺点是有特殊字符, 需要加replace 来做处理。
(2)sha1(os.urandom(24)).hexdigest()使用举例:>>> import hashlib>>> import os>>> hashlib.sha1(os.urandom(24)).hexdigest()'21b7253943332d0237a720701bcb8161b82db776'总结:这种算法的优点是安全,不需要做特殊处理。缺点是覆盖范围差一些。(3)uuid4().hex使用举例:>>> import os>>> import uuid>>> uuid.uuid4().hex'c58a80d3b7864b0686757b95e9626e47'总结:Uuid使用起来比较方便, 缺点为安全性略差一些。
(4)base64.b32encode(os.urandom(20))/base64.b64encode(os.urandom(24))使用举例:>>> import base64>>> import os>>>base64.b32encode(os.urandom(20))b'NJMTBMOYIXHNRATTOTVONT4BXJAC25TX'>>>base64.b64encode(os.urandom(24))b'l1eU6UzSlWsowm8M8lH5VaFhZEAQ4kQj'总结:可以用base64的地方,选择binascii.b2a_base64是不错的选择根据W3的SessionID的字串中对identifier的定义,SessionID中使用的是base64,但在Cookie的值内使用需要注意“=”这个特殊字符的存在;如果要安全字符(字母数字),SHA1也是一个不错的选择,性能也不错;
token的应用:
import hashlib# 待加密内容
strdata = "xiaojingjiaaseafe16516506ng"h1 = hashlib.md5()
h1.update(strdata.encode(encoding='utf-8'))strdata_tomd5 = h1.hexdigest()print("原始内容:", strdata, ",加密后:", strdata_tomd5)import time
import base64
import hmac# 生产token
def generate_token(key, expire=3600):r'''''@Args:key: str (用户给定的key,需要用户保存以便之后验证token,每次产生token时的key 都可以是同一个key)expire: int(最大有效时间,单位为s)@Return:state: str'''ts_str = str(time.time() + expire)ts_byte = ts_str.encode("utf-8")sha1_tshexstr = hmac.new(key.encode("utf-8"), ts_byte, 'sha1').hexdigest()token = ts_str + ':' + sha1_tshexstrb64_token = base64.urlsafe_b64encode(token.encode("utf-8"))return b64_token.decode("utf-8")# 验证token
def certify_token(key, token):r'''''@Args:key: strtoken: str@Returns:boolean'''token_str = base64.urlsafe_b64decode(token).decode('utf-8')token_list = token_str.split(':')if len(token_list) != 2:return Falsets_str = token_list[0]if float(ts_str) < time.time():# token expiredreturn Falseknown_sha1_tsstr = token_list[1]sha1 = hmac.new(key.encode("utf-8"), ts_str.encode('utf-8'), 'sha1')calc_sha1_tsstr = sha1.hexdigest()if calc_sha1_tsstr != known_sha1_tsstr:# token certification failedreturn False# token certification successreturn Truekey = "xiaojingjing"
print("key:", key)
user_token = generate_token(key=key)print("加密后:", user_token)
user_de = certify_token(key=key, token=user_token)
print("验证结果:", user_de)key = "xiaoqingqing"
user_de = certify_token(key=key, token=user_token)
print("验证结果:", user_de)
(4)cookie与session的区别
1、cookie数据存放在客户端上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE
(5)session与token的区别
1.作为身份认证 token安全性比session好,因为每个请求都有签名还能防止监听以及重放攻击
2.Session 是一种HTTP存储机制,目的是为无状态的HTTP提供的持久机制。Session 认证只是简单的把User 信息存储到Session 里,因为SID 的不可预测性,暂且认为是安全的。这是一种认证手段。 但是如果有了某个User的SID,就相当于拥有该User的全部权利.SID不应该共享给其他网站或第三方.
3.Token,如果指的是OAuth Token 或类似的机制的话,提供的是 认证 和 授权 ,认证是针对用户,授权是针对App。其目的是让 某App有权利访问 某用户 的信息。这里的 Token是唯一的。不可以转移到其它 App上,也不可以转到其它 用户上。

21.csrf豁免

CSRF防跨站攻击实现机制页面中存在{% csrf_token %}时在渲染的时候,会向Response中添加 csrftoken的Cookie在提交的时候,会被添加到请求体中, 会被验证有效性csrf(https://www.jianshu.com/p/d1407591e8de)
解决csrf的问题/csrf豁免:1 注释中间件2 在表单中添加{%csrf_token%}3 在方法上添加 @csrf_exempt

22.Model–》DB

Model -> DB迁移步骤生成迁移文件  python manage.py makemigrations执行迁移文件  python manage.py migrate迁移文件的生成根据models文件生成对应的迁移文件根据models和已有迁移文件差别 生成新的迁移文件迁移原理  了解先去迁移记录查找,哪些文件未迁移过app_label + 迁移文件名字执行未迁移的文件#django所有被迁移的数据结构都是 not null 不允许为空#添加新的字段的时候 必须指定默认值执行完毕,记录执行过的迁移文件可以指定迁移的app  python manage.py makemigrations app (app名字后面不允许加/)python manage.py migrate    重新迁移删除迁移文件migrations所涉及的迁移文件删除迁移文件产生的表删除迁移记录django-migrations

22.DB --》 Model

DB -> Model反向生成到指定得app下 --》  python manager.py inspectdb > 子App/models.py元信息中包含一个属性  managed=False   不支持迁移- 如果自己的模型不想被迁移系统管理,也可以使用 managed=False进行声明

23.模型关系

(1)一对一
应用场景用于复杂表的拆分扩展新功能OneToOneField确认主从关系,谁声明关系谁就是从表底层实现,使用外键实现的,对外键添加了唯一约束
class Student(models.Model):s_name = models.CharField(max_length=32)class IDCard(models.Model):id_num = models.CharField(max_length=18, unique=True)id_student = models.OneToOneField(Student, null=True, blank=True, on_delete=models.SET_NULL)
添加
添加主表数据def add_student(request):s_name = request.GET.get('name')student = Student()student.s_name = s_namestudent.save()return HttpResponse('添加学生成功')
添加从表数据def add_idcard(request):i_card = request.GET.get('id_num')id_card = IdCard()# 外键字段不能为空  除非设计表时 null=True,blank=trueid_card.id_num = id_numid_card.save()return HttpResponse('添加card成功')
数据绑定def bind(request):student = Student.objects.last()idcard = IdCard.objects.last()idcard.i_student = student             # 针对模型# idcard.i_student_id = student.id     # 针对表idcard.save()return HttpResponse('绑定成功')
思考:student是主表  idcard是从表1 再添加一个主表数据  然后执行绑定可不可以  可以2 再添加一个从表数据  然后执行绑定可不可以  不可以
删除
主表数据删除/on_delete默认  CASECADE默认级联数据被删除从表数据删除,主表不受影响主表数据删除,从表数据直接删除modelsSET_NULL置空前提模型设计的时候字段允许为NULL=True,blank=True常用SET_DEFAULT置为默认值前提存在默认值SET自己赋值models.PROTECT从表数据受保护的当存在级联数据的时候,删除主表数据,会抛出异常主表不存在级联数据的时候,可以删除开发中为了防止误操作,我们通常会设置为此模式
django默认是级联删除   删除主表的时候 从表数据都会删除
执行顺序是:从表的数据删除之后  主表的数据跟着删除def delete_student(request):student = Student.objects.get(pk=1)student.delete()return HttpResponse('删除成功')
# 删除从表数据 与主表无关
def delete_idcard(request):idcard = IdCard.objects.get(pk=1)idcard.delete()return HttpResponse('删除成功')
外键的字段的约束  如果将on_delete修改为models.PROTECT 那么如果有级联关系 删除主表的时候 会抛异常
如果没有级联关系  那么就会直接删除
#如果主表下有对应的从表数据,那么就不允许删除  没有对应的数据 才能删除
def deleteprotect_student(request):student = Student.objects.get(pk=3)student.delete()return HttpResponse('删除成功')
外键的字段的约束  如果将on_delete设置为models.setnull  那么如果有级联关系 会将从表的外键设置为null
主表数据也会删除   如果没有级联关系  会直接删除主表数据
def deletesetnull_student(request):student = Student.objects.get(pk=4)student.delete()return HttpResponse('删除成功')
删除后为 系统设置为 models.set默认值情况  (数据库会自动将将外键设置为默认值(4))
class IdCard(models.Model):cardnum = models.IntegerField()# 删除主表数据  从表数据的外键设置默认值i_student = models.OneToOneField(Student,null=True,blank=True,on_delete=models.SET(4))class Meta:db_table = 'idcard'def deleteSet(request):s = Student.objects.first()s.delete()return HttpResponse('删除主表数据, 从表设置为默认值')
查询
查询/获取从获取主显性属性该显性属性会返回一个对象主获取从隐性属性默认就是从表模型名小写该表模型名 会返回一个对象
根据idcard 获取student    显性属性
def get_student(request):idcard = IdCard.objects.get(pk=3)print(idcard.i_student.s_name)return HttpResponse('查询student')
根据student 获取 idcard
def get_idcard(request):student = Student.objects.get(pk=2)主查从   获得主表的对象之后 该对象 有一个属性 是隐形属性  #因为是一对一所以该隐性属性没有_set这个属性 是外键那个模型的小写print(student.idcard.i_card)return HttpResponse('查询idcard')1v1: student.idcard1vm: student.idcard_set
(2)一对多
class Dept(models.Model):d_name = models.CharField(max_length=32,unique=True)class Emp(models.Model):e_name = models.CharField(max_length=32)#外键默认不能为空e_dept = models.ForeignKey(Dept,null=True,blank=True,on_delete=models.SET_NULL)
添加:
外键不能为空
def add_dept(request):d_name = request.GET.get('name')dept = Dept()dept.d_name = d_namedept.save()return HttpResponse('插入dept成功')
# 外键不能为空 需要在model中设置 null=true  blank=true
def add_emp(request):e_name = request.GET.get('name')emp = Emp()emp.e_name = e_name    emp.save()return HttpResponse('插入emp成功')
def bind(request):dept = Dept.objects.last()emp = Emp.objects.last()emp.e_dept = deptemp.save()return HttpResponse('绑定成功')
删除:

数据删除同一对一一样

删除主表数据 默认级联从表数据
修改on_delete属性为models.PROTECT有级联数据数据 抛异常没有级联数据 可以正常删除
修改on_delete=models.SET_NULL有级联数据 外键值设置为null没有级联数据 直接删除
删除字表数据 不管字表返回得是列表还是单个数据 都可以直接删除  应用场景 多选删除
删除默认是级联删除
def deletedept(request):dept = Dept.objects.get(pk=2)dept.delete()return HttpResponse('删除成功')
删除从表的时候  会将所有符合条件的删除
def deleteemp(request):Emp.objects.filter(e_dept_id=1).delete()return HttpResponse('删除成功')
def deleteprotectdept(request):dept = Dept.objects.get(pk=3)dept.delete()return HttpResponse('删除成功')
def deletesetnulldept(request):dept = Dept.objects.get(pk=1)dept.delete()return HttpResponse('删除成功')
查询:

级联对象获取

从获取主显性属性
主获取从隐性属性默认是 模型小写_set该属性得返回值类型是relatedManager类型注意relatedManager是一个不可以迭代得对象  所以需要调用Manager得方法relatedManager也是Manager的一个子类filterexcludeall切片...
def finddept(request):emp = Emp.objects.get(pk=7)print(emp.e_dept)return HttpResponse('查询成功')
def findemp(request):dept = Dept.objects.get(pk=4)一对多的时候 如果通过主查从  那么主的对象调用从的模型小写_set   xxx_set方法的返回值类型是RelatedManagerRelatedManager对象可以调用all  fiter exclude。。。。。。emps = dept.emp_setfor emp in emps.all():print(emp.e_name)return HttpResponse('查询成功')
(3)多对多
ManyToManyField
产生表的时候会产生单独的关系表
关系表中存储关联表的主键,通过多个外键实现的,多个外键联合唯一
会产生额外的关系表表中使用多个外键实现外键对应关系表的主键
class Custom(models.Model):c_name = models.CharField(max_length=32)class Goods(models.Model):g_name = models.CharField(max_length=32)g_custom = models.ManyToManyField(Custom)
添加:
主添加从customer.goods_set.add(goods)隐性属性
从添加主goods.g_customer.add(customer)显性属性
需要注意的是:关系表中外键的联合唯一
def addcustom(request):custom = Custom()custom.c_name = 'zs1'custom.save()return HttpResponse('添加成功')def addgoods(request):goods = Goods()goods.g_name = '小当家1'goods.save()return HttpResponse('添加成功')
从 -- 主   从对象.属性.add(主对象)
首先必须有数据才可以插入 该数据必须是查询出来的
def addgoods1(request):custom = Custom.objects.get(pk=1)goods = Goods.objects.get(pk=1)goods.g_custom.add(custom)# goods.save() 没有实际作用return HttpResponse('添加成功')
主 -- 从   主对象.从模型名_set.add(从对象)
def addcustom1(request):custom = Custom.objects.get(pk=3)goods = Goods.objects.get(pk=3)custom.goods_set.add(goods)return HttpResponse('添加成功')
删除:
goods.g_customer.remove(customer)显性属性
custom.goods_set.remove(goods)隐性属性
删除  eg:删除用户  那么关系表的数据会不会删除
会删除  默认是级联删除   不建议
def deletecustom(request):custom = Custom.objects.get(pk=1)custom.delete()return HttpResponse('删除成功')
删除    从 -- 主  从对象.属性.方法(主对象)
def deleterelation(request):custom = Custom.objects.get(pk=2)goods = Goods.objects.get(pk=2)goods.g_custom.remove(custom)return HttpResponse('删除成功')
删除   主 -- 从   主对象.属性.方法(从对象)
def deleterelation1(request):custom = Custom.objects.get(pk=3)goods = Goods.objects.get(pk=3)custom.goods_set.remove(goods)return HttpResponse('删除成功')
查询:
对象.属性.方法
customer.goods_set.all()
从 -- 主  显性属性
def findrelation(request):goods = Goods.objects.get(pk=3)gs = goods.g_custom.all()print(gs)return HttpResponse('查询成功')
def findrelation1(request):custom = Custom.objects.get(pk=3)print(custom.goods_set.all())return HttpResponse('查询成功')

24.模型继承

模型继承的意思就是公用某些属性 但是并不是降低效率
默认一个模型在数据库中映射一张表
如果模型存在继承的时候,父模型产生表映射
子模型对应的表会通过外键和父表产生关联
从表外键引用主表得主键不能说从表外键引用主表得主键就一定是模型继承 因为一对一 一对多 都会引用主表得主键
关系型数据库性能数据量越大性能越低关系越多越复杂越低性能越低
抽象模型在父类的Model的元信息中添加  abstract=Trueclass Meta:abstract=True抽象的模型不会在数据库中产生表子模型拥有父模型中的所有字段class Animal(models.Model):a_name = models.CharField(max_length=16)class Meta:abstract = Trueclass Cat(Animal):c_eat = models.CharField(max_length=32)class Dog(Animal):d_legs = models.IntegerField(default=4)

25.静态资源

静态资源静态资源和模板的区别(1)模板的路径不可以直接访问  必须通过请求来访问static资源可以直接访问(2)模板的语法不可以在静态资源中书写注意:(1)使用的时候注意配置资源位置STATICFILE_DIRS使用  {% load static %}{% static '相对路径' %}(2)全栈工程师   要求会templates开发工程师   前后端分离static

26.文件上传

要求:客户端必须使用POST指定enctype='multiplepart/form-data'
原生代码:适用django也适用于flask从request.FILES中获取到上传上来的文件打开一个文件,从上传上来的文件进行读取,向打开的文件中进行写入必须以二进制的格式来书写每次写入记得 flushdef upload_file(request):if request.method == "GET":return render(request, 'upload.html')elif request.method == "POST":icon = request.FILES.get("icon")print(type(icon))with open("/home/xxx/xxx/Day06/xxx/static/img/icon.jpg", 'wb') as save_file:for part in icon.chunks():save_file.write(part)save_file.flush()return HttpResponse("文件上传成功")实现步骤:(1)表单得请求方式是post(2)添加表单得属性 enctype='multipart/form-data'  二进制传输(3)input得type属性值为file(4)获取表单中得file值  request.FILES.get获取的是文件的名字(5)with open打开一个路径,然后以wb的模式使用for i in xxx.chunks()fp.write()fp.flush()fp.close()
Django内置:(1)创建模型并且指定ImageField属性(注意依赖于pillow,pip install pillow)eg:u_icon = models.ImageField(upload_to='icons')imageField在数据库中的数据类型是varchar,默认长度为100(2)settings中指定 MEDIA_ROOTMEDIA_ROOT = os.path.join(BASE_DIR, 'static/upload')注意:media_root后面的数据类型不是一个列表会自动的创建文件夹该文件夹的路径是MEDIA_ROOT + ImageField的upload_to的值注意:1:重复添加同一个图片,那么会直接添加进去,文件的名字是文件名原名+唯一串2:数据库icon的值是upload_to + 文件名字隐藏bug:linux系统下文件夹的第一级子目录下 最多存储65535个文件u_icon = models.ImageField(upload_to='%Y/%m/%d/icons')支持时间格式化%Y%m%d%H%M%S...专门用来解决linux的bug的   文件夹的第一级字目录下 最多存储65535个文件案例:def image_field(request):if request.method == "GET":return render(request, 'image_field.html')elif request.method == "POST":username = request.POST.get("username")icon = request.FILES.get("icon")user = UserModel()user.u_name = usernameuser.u_icon = iconuser.save()return HttpResponse("上传成功%d" % user.id)模型:class UserModel(models.Model):name = models.CharField(max_length=64)#ImageField依赖Pillow库 所以需要安装  pip install pillow#upload_to 依赖MEDIA_ROOTicon = models.ImageField(upload_to='%Y/%m/%d/icons')实现步骤:(1)表单的提交方式必须是post # 执行一个请求,跳转到一个页面(2)添加表单的属性enctype = mutipart/form-data(3)在settings中设置MEDIA_ROOT = os.path.join(BASE_DIR,'static/upload')(4)创建模型  模型的属性是imagefield (5)注意imagefield依赖于pillow  # 需要安装(6)imagefield的约束是upload_to  路径是upload_to和MEDIA_ROOT的拼接(7)实例化对象 然后save保存即可

27.缓存

目的:缓解服务器的读写压力提升服务器的响应速度提升用户体验将执行过的操作数据 存储下来,在一定时间内,再次获取数据的时候,直接从缓存中获取比较理想的方案,缓存使用内存级缓存(redis)Django内置缓存框架存储中间数据的一种介质
Django内置缓存实现(三种方案)
(1)使用系统封装的装饰器封装在视图函数上@cache_page(30)需要注意的是不需要写timeout模板中也可以缓存--django内置得数据库缓存@cache_page(30)def testCache1(request):time.sleep(5)return HttpResponse('testCache1')
(2)基于数据库:在真实的数据库中去创建缓存表(1)创建缓存表python manage.py createcachetable [table_name](2)settings中配置缓存信息CACHESdefault'BACKEND': 'django.core.cache.backends.db.DatabaseCache''LOCATION': 'my_cache_table''TIMEOUT': 60 * 5  缓存时间以set方法为主eg:CACHES={'default':{'BACKEND':'django.core.cache.backends.db.DatabaseCache',# 缓存位置'LOCATION':'my_cache_table',# 过期时间'TIMEOUT':60,'KEY_PREFIX':'python190x',}}
(3)基于redis-内存级数据库Django-redis-cache使用redis实现django-cache的扩展操作缓存的API没有发生任何变更变更的就是连接缓存的配置常见的有两个实现django-redis http://django-redis-chs.readthedocs.io/zh_CN/latest/#djangopip install django-redisdjango-redis-cachehttps://pypi.python.org/pypi/django-redis-cache/pip install django-redis-cache基本配置CACHES={'default':{'BACKEND':'django_redis.cache.RedisCache','LOCATION':'redis://127.0.0.1:6379/1','OPTIONS':{'CLIENT_CLASS':'django_redis.client.DefaultClient'},'KEY_PREFIX': 'python2001',},}查看redis缓存select 1keys *get :1:news查看过期时间  tts  :1:news如果你的redis中报错  端口号已经被占用 则因为你的服务已经被开启。
可使用 ps -ef | grep -i redis 查看如果已经开启,不要急于杀死进程
解决策略:将settings 中的配置redis的主机地址设置为127.0.0.1如果连接redis的时候 转圈
解决策略:
(1)查看云主机的入方向和出方向的端口  必须要开放6379端口
基本端口号:22 ssh  80 http  443 https  3306 mysql  6379 redis  8000 django默认端口
入方向和出方向 必须一致以下策略基本上在Linux操作系统 出现概率不大 如有则按照下述设置
(2)配置文件中 不允许远程连接56行 代码 是 bind 127.0.0.1  将这行代码注释  因为 默认是只允许本地连接75行  代码 是 protect_model = yes 修改为no
多缓存:
CACHES = {'default': {'BACKEND': 'django.core.cache.backends.db.DatabaseCache','LOCATION': 'my_cache_table','TIMEOUT': 60 * 5},'redis_backend': {"BACKEND": "django_redis.cache.RedisCache","LOCATION": "redis://127.0.0.1:6379/1","OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient",}}
}写多套配置,定义不同的名字存入缓存的时候,获取不同的缓存对象想使用哪个缓存就创建哪个缓存的实例对象装饰器缓存@cache_page(30, cache='cache_name') 可以使用装饰器 指定想要的数据库数据库缓存/redis缓存cache = caches['cache_name']   多集缓存_缓存实际就近原则

28.中间件

中间件:是一个轻量级的,底层的插件,可以介入到Django的请求和响应过程(面向切面编程)
中间件的本质就是一个python类
面向切面编程(Aspect Oriented Programming)简称AOP。AOP的主要实现目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合的隔离效果。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N6gMC4nJ-1590765405598)(C:\Users\ADMINI~1\AppData\Local\Temp\1588730301233.png)]

django内置的一个底层插件
从属于面向切面编程AOP在不修改源代码的情况下,动态去添加一些业务逻辑处理
中间件的典型实现 装饰器中间件就是使用类装饰实现的
面向切面编程切点(1)process_requestprocess_request(self,request):在执行视图前被调用,每个请求上都会调用,不主动进行返回或返回HttpResponse对象(2)process_viewprocess_view(self,request,view_func,view_args,view_kwargs):调用视图之前执行,每个请求都会调用,不主动进行返回或返回HttpResponse对象(3)process_template_response    process_template_response(self,request,response):在视图刚好执行完后进行调用,每个请求都会调用,不主动进行返回或返回HttpResponse对象(4)process_responseprocess_response(self,request,response):所有响应返回浏览器之前调用,每个请求都会调用,不主动进行返回或返回HttpResponse对象(5)process_exceptionprocess_exception(self,request,exception):当视图抛出异常时调用,不主动进行返回或返回HttpResponse对象切面切点处切开可以获得的数据
实现步骤:
书写,自定义中间件1. 在工程目录下创建middleware目录2. 目录中创建一个python文件3. 在python文件中导入中间件的基类from django.utils.deprecation import MiddlewareMixin4. 在类中根据功能需求,创建切入需求类,重写切入点方法class LearnAOP(MiddlewareMixin):def process_request(self,request):print('request的路径',request.GET.path)5. 启用中间件,在settings中进行配置,MIDDLEWARE中添加middleware.文件名.类名6.中间件有返回值时不执行视图函数的返回值。所以中间件不设返回值7.默认情况下,中间件是在所有视图函数前执行的。所以需要过滤,把一些请求资源路径顾虑掉# 连接数据库例子CONN_REQ = ['/final/add/','/final/delete/','/final/find/',]if request.path in CONN_REQ:print('中间件连接数据库')
应用:白名单def get_phone(request):if random.randrange(100) > 95:return HttpResponse("恭喜你抢到了小米8")return HttpResponse("正在排队")if request.path == "/app/getphone/":if ip == "127.0.0.1":if random.randrange(100) > 20:return HttpResponse("恭喜您免费获取小米8 256G版")黑名单if request.path == "/app/getticket/":if ip.startswith("10.0.122.1"):return HttpResponse("已抢光")作业:如果一分钟之内访问了10次 那么返回 小爬虫快走开,如果1分钟之内访问了30次 封ip 5分钟  正常访问 返回来了老弟   (cache + 中间件)
在中间件中判断所有的的视图函数,如果有异常,则执行process_exception
当某一段业务逻辑发生了错误  那么就会执行process_exception方法
process_exception界面友好化 应用交互友好化def process_exception(self, request, exception):print(request, exception)return redirect(reverse('app:index'))
注意:中间件的执行顺序中间件注册的时候是一个列表如果我们没有在切点处直接进行返回,中间件会依次执行如果我们直接进行了返回,后续中间件就不再执行了

29.分页器

分页是为了提升用户体验,并且减小服务器的负担而开发的
分页:真分页   每一次点击下一页或者上一页 都会向数据库发送请求 并且返回数据    访问数据库次数过多假分页   一次性读取所有数据  然后再内存中进行分页  内存压力太大企业级开发中常用 真分页
原生实现传时 要加上int偏移加限制offset  limitstudents = Student.objects.all()[per_page*(page-1): page * per_page]# extdef testGetPage(request):page = int(request.GET.get('page',1))per_page = int(request.GET.get('per_page',5))# 一页5条sutdent_list = Student.objects.all()[per_page*(page-1): page * per_page]for sutdent in sutdent_list:print(sutdent.id,sutdent.name)return HttpResponse('道不同不相为谋')
封装实现Paginator(分页工具)对象创建:Paginator(数据集,每一页数据数)paginator = Paginator(students, per_page)属性count对象总数num_pages:页面总数page_range: 页码列表,从1开始  *方法:page(整数): 获得一个page对象该方法的返回值类型是Page常见错误:InvalidPage:page()传递无效页码PageNotAnInteger:page()传递的不是整数Empty:page()传递的值有效,但是没有数据Page(具体哪一页)对象获得通过Paginator的page()方法获得属性object_list: 当前页面上所有的数据对象number:  当前页的页码值paginator:   当前page关联的Paginator对象方法has_next()    :判断是否有下一页has_previous():判断是否有上一页has_other_pages():判断是否有上一页或下一页next_page_number():返回下一页的页码previous_page_number():返回上一页的页码len():返回当前页的数据的个数应用场景:paginator对象  适用于 页码的遍历  eg 上一页 xxx  下一页page对象       适用于 是否有上一页 下一页  上一页页码  下一页页码
#ext 封装实现
def testDjangoPage(request):pag = request.GET.get('page',1)per_page = request.GET.get('per_page',5)student_list = Student.objects.all()# Paginator的参数有objectpaginator = Paginator(student_list,per_page)# 适用于上一页和下一页之间的页码# for i in paginator.page_range:#     print(i)# # 总页数# print(paginator.num_pages)# # 一共有多少条# print(paginator.count)# page 对象# page方法返回了一个Page对象。该对象中是否有上一页,是否有下一页# 上一页页码  下一页页码pa = paginator.page(pag)pa.has_next()pa.has_previous()pa.next_page_number()pa.previous_page_number()return HttpResponse('Django分页')

30.富文本

富文本富文本:Rich Text Format(RTF),是有微软开发的跨平台文档格式,大多数的文字处理软件都能读取和保存RTF文档,其实就是可以添加样式的文档,和HTML有很多相似的地方写论坛,博客时使用的一种带样式的文本插件插件使用方式(1)安装插件pip install django-tinymce == 2.8.0(2)在instatlled_app中添加tinymce(3)初始化在settings中注册tinymce应用设置默认的配置文件TINYMCE_DEFAULT_CONFIG = {'theme':'advanced','width':800,'height':600,}(4)创建模型from tinymce.models import HTMLFieldclass Blog(models.Model):sBlog = HTMLField()(5)使用在自己的页面中使用对应的输入方式 文本域 <textarea></textarea>引入tinymce<script type="text/javascript" src="/static/tiny_mce/tiny_mce.js"></script>初始化绑定文本域<script type="text/javascript">tinyMCE.init({"mode": "textareas","theme": "advanced","width": 800,"height": 600})</script>

(L159951)Django2001相关推荐

  1. Django学习笔记(下)

    文章目录 18 Template概念 19 模版语法 19.1 变量 19.2 点语法 19.3 标签 20 常见的请求状态码 21 view视图函数 21.1 概念及基础语法 21.2 内置函数 2 ...

  2. Django的边边角角(二):缓存、中间件、分页器、富文本

    文章目录 一.缓存 1.概述 2.Django内置缓存实现 (1)装饰器缓存 (2)数据库缓存 (3)内存级数据库缓存(redis) 3.多级缓存 (1)多级缓存 - 装饰器缓存 (2)多级缓存 - ...

最新文章

  1. rat/rats--用有理数形式表示矩阵
  2. 精益分析体系构建如何“因企制宜”?
  3. 如何扩展开发团队(转)
  4. .Net Aop(静态织入)框架 BSF.Aop
  5. python django开发工具_Django+python 开发神器
  6. python调用函数获取最开始的异常_Python使用sys.exc_info()方法获取异常信息
  7. C#集成FastDFS断点续传
  8. chage 修改用户密码的有效期限
  9. 【数据融合】基于DS证据理论实现数据融合附matlab代码
  10. 世界杯来了,移动办公的“世界杯”怎么踢?
  11. 电子技术基础(三)_第4章直流稳压电源__集成稳压器
  12. js 检测浏览器开发者控制台是否被打开
  13. matlab里pascal是什么意思_台球里的自然角是什么意思
  14. python 设计单张扑克牌类Card 设计整副扑克牌类Cards
  15. win10驱动开发16——派遣函数(直接方式读操作)
  16. 《黑客大曝光:移动应用安全揭秘及防护措施》一2.1 基础移动网络功能
  17. 校招前端笔试面试回顾
  18. 【电子科学系保研】-- 湖南大学保研之旅
  19. 电大计算机基础期末考试题库,中央电大计算机基础考试题库大全
  20. pandas中的.astype()使用规范问题——以.astype(int)的一种str类型数据转int类型数据报错为例

热门文章

  1. Python神奇的海象运算符:=使用教程
  2. 面试题目总结(1) https中间人攻击,ConcurrentHashMap的原理 ,serialVersionUID常量,redis单线程,
  3. Python语言-NL-工作日的力量
  4. 深度学习之pix2pix原理解析
  5. MOBA游戏战斗服务器设计思路
  6. 《机器人操作系统ROS原理与应用》——1.3 智能机器人的分类
  7. 解决微信小程序报[ app.json 文件内容错误] app.json: app.json 未找到,未找到入口 app.json 文件,或者文件读取失败,请检查后重新编译。小程序app.json报错
  8. SpringCloud断路器——Hystrix
  9. 【软件测试】老板:你测试,我放心。测试人的成功就是不做测试?
  10. 微信服务号自定义服务器配置及验证