青魔法圣堂法术 Django的技术栈(持续更新)
青魔法圣堂法术Django不管在哪一种圣堂法术中都属于佼佼者。
**跳转到文章结尾**
链接:https://www.cnblogs.com/Asterism-2012/p/10046765.html#head
目录
开发环境
- 操作系统:win10
- Python版本:3.6.5
- 集成开发工具:Pycharm
- MySQL数据库版本:5.7以上
推荐书单与学习网站:
- Django官方文档
- Django Github源码
Django-Web框架
django是一个web框架。(音标:[dʒæŋɡoʊ])
Django用于快速开发数据驱动网站。他几乎为我们封装好了开发站点所需要做的一切冗余操作。(避免重复造轮子,并且无需了解与服务器沟通的过程)
就像是我们只需要制作玩具车的零件,Django框架为我们做好需要生产出一个玩具车的一切。
(在学习此课程之前,我们要确保我们电脑上已经安装了所需的Python、Django、Mysql等环境,框架,数据库并且配置好相关的环境变量)
Django的发布时间是:2005年。
http报文的学习很重要
——学习Web开发不好好学习HTTP报文,将会“打拳不练功,到老一场空”,你花在犯迷糊上的时间比你沉下心来学习HTTP的时间肯定会多很多。
(HTTP报文解释:https://blog.csdn.net/zhll3377/article/details/7748086)
学习Django入门的两个步骤:
什么是Web框架?
Web框架为应用程序提供了一套程序框架,这样你可以++专注++于编写清晰、易维护的代码,++而无需从头做起。++ 简单来说,这就是Django所能做的。
Django学习的三个参考:1.Django官网,2.Django源码——Github,3.官方文档(参考自传智播客)
阅读【django源码】
MVC 与 MVT for Django
一. MVC(Model-View-Controller 三层功能模块)
(1)核心思想:解耦。
++降低++模块之间的++耦合++,增强扩展性和移植性。并且向后版本兼容。
松散的三部分组合在一起就是模型-视图-控制器(MVC)的设计模式。简单的说,++MVC++是一种++软件开发的方法++,它把:
a. 代码的定义和数据访问的方法(模型)与
b. 请求逻辑 (控制器)还有
c. 用户接口(视图)这三部分分离开来。
(2)开发原则:高内聚,低耦合。
高内聚的意思是,逻辑严谨,通过继承体现。
MVC解析:1.Model:封装对数据库的访问,内嵌ORM框架。
2. View:封装结果,内嵌模板引擎(.html)展示数据
3. Controller:处理请求、业务逻辑、与M、V交互。它是MVC的核心。
二. MVT(Model-View-Template 三层功能模块)
核心思想:解耦。
开发原则:高内聚,低耦合。
MVC解析:
- Model:与MVC的M相同。
- View:与MVC的C相同。
- Template:与MVC的V相同。
三. [ORM框架]:
- 对象-关系-映射 的简称
- 内嵌于Model中.是别人写来专门与数据库交互的框架。被django开发者直接拿来使用,因为很好用。
它的特点是:- 以面向对象的形式操作数据库。
通过模型类和对象的++映射关系++来完成CRUD(“增删改查”)。 - 把数据库的行与相应的++映射对象++建立关联,互相转换,是自身无需直接操作库。把查询到的结果转化为对象、列表(我觉得是结果集)。
- 以面向对象的形式操作数据库。
低耦合与高内聚:
内聚性:功能强度的度量,通过继承体现(语名间,程序段间)模块内部个元素彼此的紧密程度(逻辑性)。
耦合性(coupling):耦合高低取决于模板间接口的复杂性,调用的方式以及传递的信息。耦合性也叫块间联系。指软件系统结构中各模块间相互联系紧密程度的一种度量。模块之间联系越紧密,其耦合性就越强,模块之间越独立则越差。耦合性就是模块与模块之间的亲密关系,关系亲密则依赖度高,若否则易于移植和拓展。
虚拟环境的使用:
为什么使用虚拟环境? 搭建独立python运行环境。防止相同包的不同版本之间相互冲突和覆盖.
- 目录:/home/.virtualenvs 可以移动进去进行修改数据
- 安装虚拟环境的详情请参照灵蛇法术篇。
Ajax:
MVT丢掉Template,依然可以进行数据请求(交互),Ajax请求用json进行交互.这体现了解耦(前后端分离).
Django自带的的轻量级服务器的启动:
Django为我们准备了一个轻量级的Web开发服务器。仅用于开发阶段使用。
(Py_Django2.0.6) E:\Git\demo_project>python manage.py runserver
Django开发步骤:
- 安装Django, 指定版本是2.0.6
pip install django==2.0.6
- 查看Django版本(In shell):
import django
django.get_version()
- 创建项目(In shell):
(Py_Django2.0.6) E:\Git>django-admin startproject demo_project
- 创建应用
(Py_Django2.0.6) E:\Git>cd demo_project
(Py_Django2.0.6) E:\Git\demo_project>python manage.py startapp demoapp
Django项目文件解析:
先看一下表结构:
卷 Work & Learn 的文件夹 PATH 列表
卷序列号为 0EA8-9214
E:.
│ manage.py
│
├─demo_project
│ │ settings.py
│ │ urls.py
│ │ wsgi.py
│ │ __init__.py
│ │
│ └─__pycache__
│ settings.cpython-35.pyc
│ __init__.cpython-35.pyc
│
└─demo_app
│ admin.py
│ apps.py
│ models.py
│ tests.py
│ views.py
│ __init__.py
│
└─migrations
__init__.py
项目文件目录说明:
manage.py
: 一个++命令行工具++,与项目进行交互demo_project
:项目的同名文件,这个是随着项目的名称改变二改变的: 项目配置文件的存放位置,真正意义上的python
包。
项目的同名文件(HELLO)下:(项目真正的python包)
__init__.py
: 一个空文件,告诉python该目录是一个Python包。settings.py
: 该Django项目的++设置和配置++urls.py
: 该项目的url声明,一份由django驱动的"++网页目录++"wsgi.py
一个WSGI++兼容的服务器入口++,以便运行你的项目
应用于项目同名文件间无关系,无依赖。需要安装应用来使用。
应用下的文件:
urls.py
: 用于定义子路由, 但是这个文件不是django自带的,需要手动创建。通常用正则表达式来表示url,本质是视图与模板之间的映射关系表。
import django.conf.urls import url # 导入url
from .views import DemoView
urlpatterns = [
url(r'^index/$', DemoView);
]
models.py
: 模型层的主要内容
用于定义模型类,定义表结构,以便用于存放数据。
这些内容其实可以好好研究一下,但是这不是目前主要的学习内容,可以稍后进行学习。
settings.py
文件配置介绍
- 监听IP地址 就是说允许这个地址来访问我们的web服务器,如果填写”*“号则表示允许所有网段的设备进行访问。
ALLOWED_HOSTS = ["*"] # 原本这里是一个空列表,但是现在就代表开放了访问,也可以进行指定IP如 10.30.36.111的设备。
- 根路径指定:
BASE_DIR (根路径指定)
- 主路由指定:
ROOT_CONF (主路由指定)
- 安装应用:
django自身自带着很多应用,存放在INSTALL_APPS列表中,我们可以把开发所需要需要的第三方应用以及我们创建的应用追加到列表中。
INSTALL_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 这个是我的应用,这里是标准写法,也可以简化为‘demo_app’
'demo_app.apps.DemoAppConfig',
]
ENGINE(引擎)
在项目setting.py中添加应用的做法可以叫做安装应用, 也可以叫做注册应用。
- 在settings.py中安装数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test2',
'USER': '用户名',
'PASSWORD': '密码',
'HOST': '数据库服务器ip,本地可以使用localhost',
'PORT': '端口,默认为3306',
}
}
-
其实django.db.backends.mysql 意思就是 指向django/db/backends/mysql这个目录内写好的代码:他们都是Django开发者写好支持面向对象操作数据库的,默认状态下只支持四个写好的,如果需要额外的数据库来工作,那么可以自己写,自己写,自己写,对。
-
项目配置目录下的
__init__.py
文件设置,要写上这一行代码,表示在django上安装了Mysql客户端:
import pymysql
pymysql.install_as_MySQLdb()
SQLite3 数据库
SQLite3 是一个django自身支持的数据库
开发流程纲要:
- 如果存在的话:首先创建好放置templates模板文件和static静态文件的文件夹
- 配置setting:安装应用、设置模板路径、设置静态文件路径
- 配置主路由,并且在应用中配置好子路由
- 配置数据模型类
- 配置Views视图中的业务逻辑
(这是一个典型的后台思维的做法,这是一个很好的流程,但事实上,这并不要求你一定要按照这个流程去开发站点,却很有利于新手的掌握。)
MVT中的M:模型——Models.py
- 首先要注意的事是每个数据模型都是 django.db.models.Model 的子类。它的父类 Model 包含了所有必要的和数据库交互的方法,并提供了一个简洁漂亮的定义数据库字段的语法。 信不信由你,这些就是我们需要编写的通过Django存取基本数据的所有代码。
每个模型相当于单个数据库表,每个属性也是这个表中的一个字段。 属性名就是字段名,它的类型(例如 CharField )相当于数据库的字段类型 (例如 varchar )
定义模型
说明:
- 排序会增加数据库的开销:在磁盘的物理占用会变大
- django根据属性的类型确定以下信息:
- 当前选择的数据库支持字段的类型
- 渲染管理表单时使用的默认html控件
- 在管理站点最低限度的验证
- Django根据属性的类型确定以下信息:
- 字段类型与约束条件
- 渲染管理表单时使用的默认html控件
- Django会默认生成主键字段(id)。我们也可以自己定义,这样他就不会自己再生成。
- 字段名不能包含两个连续下划线:如a__b;(会影响查询的标识符)
- isDelete 写在前面:它不是一个字段类型,进行数据保护的一个布尔类型字段,称为逻辑删除。
代码:
CharField是字段类型,max_length是约束条件(可以叫做字段属性)。
BooleanField是字段类型,default是字段属性。
定义字段
上面的代码已经进行示例过了,这是一个详细说明。
- 导入from django.db import models
- 通过models创建字段类型的对象,并且赋予一个属性名
- 对于重要的数据,都做逻辑删除,不做物理删除,实现方法是定义isDelete属性,类型为BooleanField,默认值为False。
- DateField(如果不写参数,则可以(需要)自己维护)
- 没有特别需要,我们不使用上传文件、上传图片字段。而是我们直接上传文件到服务器磁盘的目录中,将其路径存下来(当作字符串)使用。图片等媒体文件在数据库中的保存方式是二进制方式保存,它们体积太大,会占用太多的资源。
- default默认值约束,更像是django的逻辑约束,而不是物理约束。它不应用于数据库,只决定于对象字段如何创建。
进行数据迁移
生成迁移就是生成模型类与数据库之间的映射表,使django的开发者能够使用models中的增删改查的方法来直接操作数据库,而无需懂得SQL语句。(除非你是一个业余爱好者,否则其实还是要懂的,程序员不懂不行啊)。
- 首先要将APP 添加到settings.py配置文件的INSTALL_APPS中去。
否则在生成数据迁移的时候django会找不到你的应用。
则会显示:No changes detected 没有变化检测
No changes detected
-
这里使用的是文档型数据库SQLite3,这样就无需配置。当然也可以使用MySQL数据库或者其他数据库。反正我不是嫌麻烦嘛。mysql数据库的配置可以在“settings.py 文件配置介绍”中查阅。
-
首先进行生成迁移文件,统称生成迁移。
(Py_Django2.0.6) E:\Git\demo_project>python manage.py makemigrations
成功则显示是这样的。
这个时候就可以看到迁移文件已经生成了。可以来这个文件里面看它的源码,这就是这个。但是这一步只是生成了一个迁移文件,而没有在数据库中创表。
- 所以要进行执行迁移文件,就叫执行迁移。
(Py_Django2.0.6) E:\Git\demo_project>python manage.py migrate
成功之后的显示:
查看一下数据库,表已经建立好了:
字段类型
说明表:
- AutoField:一个根据实际ID自动增长的IntegerField,通常不指定
如果不指定,一个主键字段将自动添加到模型中- BooleanField:true/false(布尔映射mysql是tinyint类型的) 字段,此字段的默认表单控制是CheckboxInput
- NullBooleanField:支持null、true、false三种值
- 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实例来表示的浮点数
- 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, 这个字段在表中必须有唯一值
- verbose_name:定义字段名。与db_column不同,它是面向用户的。
元选项(元类)
- 在模型类中定义类Meta,用于设置元信息,获取查询数据的时候,默认(由小到大)给数据的显示方式。
class Meta:
- 元信息db_table:定义数据表名称用的,指定一个字符串作为表的名称,如果不使用,系统也会自动生成表的名称。
class Meta:
db_table='新的数据表名称'
- ordering排序:对象的默认排序字段,获取对象的列表时使用,接收属性构成的列表。排序会增加数据库的开销:在磁盘的物理占用会变大
class BookInfo(models.Model):
...
class Meta():
ordering = ['id'] # 字符串前加-表示倒序,不加-表示正序
class BookInfo(models.Model):
...
class Meta():
ordering = ['-id'] # 表示倒序排序
自定义管理器:
- objects是默认的manager类型的对象,用于与数据库进行交互。
- 从哪里来的?继承来的。
- manager是django定义好的类,它是ORM的核心。
- 当定义模型类时,没有指定管理器,则django会为模型类提供一个名为objects的管理器。
- 支持自定义管理器。(支持明确指定模型类的管理器)
class BookInfo(models.Model):
...
books = models.Manager()
#注意,当我们这样做的时候。默认的object就没了
books1 = models.Mnager()
#这样做我们就要可以拥有多个管理器
#但是以上代码这样写是没有意义的
管理器对象Manager
- 管理器是Django的模型进行数据库查询操作的接口(ORM),Django应用的每一个模型都拥有至少一个管理器。
- 自定义管理器主要应用于两种情况:
-
改变默认查询集的结果,改变创建方法
-
设置模型类的创建
-
'''我们要通过自己定义的管理器的类继承Manager,通过重写++get_queryset++方法来完成更改默认查询集'''
class BookInfoManager(models.Manager):
def get_queryset(self):
return super(BookInfoManager,self).get_queryset().filter(isDelete=False)
- 注意:当为模型类指定管理器之后 ,默认的管理器就不会再生成(django不会为模型类生成名为objects的默认管理器)。
- 更深层次的理解:model层只是映射,如果数据库中已存在(并且一一对应),那么就不用迁移,可以直接使用。没错:就是这样,直接使用
通过模型类修改数据内容
hero = HeroInfo()
hero.hero_name = '俄狄浦斯'
hero.save()
通过模型类查看数据内容
外键:表之间的关系
这一个概念是基础概念,很容易理解,但是要需要多多实际练习。
- 关系的类型包括
- ForeignKey:一对多,将字段定义在多的一段端中(就是在子级表中定义一个字段指向父级表),就是外键。例如一本书中有多个英雄,在英雄表中定义“书籍字段”,指向该英雄所对应的书籍。
- ManyToManyField:多对多,将字段定义在两端中 。例如朋友与朋友之间,就是多对多,你可以是他们的朋友,他们也有自己的朋友。
- OneToOneField:一对一,将字段定义在任意一端中。比如身份证,一个人只能有一张身份证。
- 可以维护递归的关联关系,使用'self'指定,详见“自关联”
- 跨表的字段存储的原理就是相当于一个指针,存储对方的主键。类似于虫洞穿越。
三种关系之间访问方式:
- 用一访问多:对象.模型类小写_set
bookinfo.heroinfo_set
- 用一访问一:对象.模型类小写
heroinfo.bookinfo
- 访问id:对象.属性_id
heroinfo.book_id
MVT中的V:视图——Views.py
所谓的视图函数(或 视图 ),只不过是一个接受 Web 请求并返回 Web 响应的 Python 函数。实际上,该响应可以是++一份网页的 HTML 内容、一次重定向、一条 404 错误、一份 XML 、文档、一幅图片,或其它任何东西++。视图本身包含返回该响应所需的任意逻辑。
视图的本质就是函数。
- 可以将views命名为其他,但通常并非必要。除非你是独立开发一个用途不明的站点。
- 第一个参数是HttpRequest;当Django接收一个请求报文后会构造一个reqest对象,但是response需要我们自己构建
- 必须返回HttpResponse对象,或它(HttpResponse)的子类。
URLconf(url配置)
- 根级url配置:settings中>ROOT_URLCONF(自动生成)
- 子、主路由(手动配置)
- 可以将urls.py命名为其他,但通常并非必要
- 在url的正则中,用小括号括起来的部分将作为参数传递给视图函数(字符串类型)。
- 每个正则表达式前面的r表示字符串不转义
- 请求的url被看做是一个普通的python字符串,进行匹配时不包括get或post请求的参数及域名
http://www.itcast.cn/python/1/?i=1&p=new,只匹配“/python/1/”部分
- 正则表达式非命名组,通过位置参数传递给视图
url(r'^([0-9]+)/$', views.detail, name='detail'),
- 正则表达式命名组,通过关键字参数(P符传参)传递给视图,本例中关键字参数为id
url(r'^(?P<id>[0-9]+)/$', views.detail, name='detail'),
命名空间(给URL起名字)
(用于反向解析)
- 在视图函数重定向会使用到
- 模板中链接会使用到
主路由
url(r'^', include('booktest.urls', namespace='booktest')),
子路由
url(r'^([0-9]+)/$', views.detail, name='detail'),
错误视图
(当关闭调试模式,DEBUG=False时候才会启用,同时要开放访问)
- 自定义一个404.html的模板即可(在找不到页面时候系统会自动显示这个页面。)
默认的404视图将传递一个request_path参数给模板:request_path,它是导致错误的URL
...
找不到{{request_path}}这个路径
</body>
</html>
- 自定义500.html模板(视图代码运行错误时候会显示)
不会传递参数给模板 - 自定义400.html模板(错误请求:当用户进行的操作在安全方面可疑的时候,例如篡改会话cookie)
HttpRequest对象:
封装了所有请求报文。
属性
- 下面除非特别说明,属性都是只读的
- path:一个字符串,表示请求的页面的完整路径,不包含域名
- method:一个字符串,表示请求使用的HTTP方法,常用值包括:'GET'、'POST'
- encoding:一个字符串,表示提交的数据的编码方式
- 如果为None则表示使用浏览器的默认设置,一般为utf-8
- 这个属性是可写的,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的任何访问将使用新的encoding值
- GET:一个类似于字典的对象,包含get请求方式的所有参数
- POST:一个类似于字典的对象,包含post请求方式的所有参数
- FILES:一个类似于字典的对象,包含所有的上传文件
- COOKIES:一个标准的Python字典,包含所有的cookie,键和值都为字符串
- session:一个既可读又可写的类似于字典的对象,表示当前的会话,只有当Django 启用会话的支持时才可用,详细内容见“状态保持”
方法
- is_ajax():如果请求是通过XMLHttpRequest发起的,则返回True
QueryDict对象
QueryDict对象是一个类字典的对象,它的特点是:它也是以键值对的形式保存数据,但是它的每一个键都可以包括一个或多个值。也可以这么说:它的键是可以重复的。
- GET属性和POST属性都是QueryDict对象
- 方法get():根据键获取值
- 只能获取键的一个值
- 如果一个键同时拥有多个值,获取最后一个值
request.GET.get('键',default)
request.POST.get('键',default)
或简写为
request.get['键']
request.get['键]
- 方法getlist():根据键获取(多个)值
- 将键的值以列表返回,可以获取一个键的多个值
request.get.getlist('键',default)
request.POST.getlist('键',default)
在本网站中不用特意指定域名。
- 如何本页面是表单的提交页面,那么直接获取值就好了。(reques.POST)
HttpResopnse对象
是我们需要返回的一个对象。
- 调用模板(用于返回对象)的完整过程
from django.http import HttpResponse
from django.template import RequestContext, loader
def index(request):
t1 = loader.get_template('polls/index.html')
context = RequestContext(request, {'h1': 'hello'})
return HttpResponse(t1.render(context))
#加载的过程,就是将页面上的模板读过来
#然后渲染的过程,是将页面上的模板替换的过程
- render是它的简写
属性
- content:表示返回的内容,字符串类型(返回的部分:所处于body)
- charset:表示response采用的编码字符集,字符串类型
- status_code:响应的HTTP响应状态码
- content-type:指定输出的MIME类型(多媒体文件后缀名类型如.html.py等:表示为"text/html")
方法
- init :使用页内容实例化HttpResponse对象
- write(content):以文件的方式写
response.write(任何格式的数据类型)
- flush():以文件的方式输出缓存区
- set_cookie(key, value='', max_age=None, expires=None):设置Cookie
- cookie就是存储在浏览器上的一段文本信息(是response为我们返回回来的一个键值对),(之后会会自动加到请求报文头中提交请求),跨域名是不能共享cookie信息的。 但在整个域名内,cookie都可用。而且一旦写进去,会一直保存(至多两个星期)。
- key、value都是字符串类型
- max_age是一个整数,表示在指定秒数后过期
- expires是一个datetime或timedelta对象,会话将在这个指定的日期/时间过期,注意datetime和timedelta值只有在使用PickleSerializer时才可序列化
- max_age与expires二选一
- 如果不指定过期时间,则两个星期后过期
写一个cookie返回给浏览器:
response = HttpResponse()
response.set_cookie('键','值')
#在这之后,它会保存至多两周,并且在当前域名下会自动加入到请求头部(request headers)中
在服务器端接收cookie:
#获取cookie对象
cookie = request.COOKIE
if cookie.has_key
COOKIE对象的方法
cookie对象是区别于网站的,应用于当前域名内所有页面。
出于安全考虑,是浏览器提供的限定,它隔离不同的网站。
例子:京东与淘宝的推荐。无法相互读取cookie信息。
- 获取cookie对象
cookie = request.COOKIE
- 获取cookie的值
#cookie对象
cookie['键']
#或者
cookie
- 判断cookie是否拥有某个键
#这是python2中的写法
cookie.has_key('键')
#Python3是这样写的
if '键' in cookie
- 删除Cookie
response = HttpResponse('ok')
response.delete_cookie('hello')
return response
HttpResponseRedirect重定向(继承于Response)
告诉浏览器重新发送请求
- 平时还是用简写redirect重定向(简写)
预留部分:子类JsonResponse(继承于Response)
-
返回json数据,一般用于异步请求
-
_init _(data)
-
帮助用户创建JSON编码的响应
-
参数data是字典对象
-
JsonResponse的默认Content-Type为application/json
from django.http import JsonResponse
def index2(requeset):
return JsonResponse({'list': 'abc'})
状态保持
- Http是无状态的:它不会(直接)记录你之前与这个网站交互的信息。
- 会话:客户端与服务器端的一次通信,就叫做会话。
- cookie与session都可以实现状态保持:记录交互(会话相关数据)的信息。
- cookie将会话信息存储到客户端,而session将会话信息存储在服务器端。推荐使用session来存储敏感信息。
- 状态保持的目的是为了在一段时间内跟踪请求者的状态,实现跨页访问当前请求者的数据。
- 不同请求者之间相互隔离:他们不会共享session数据
- session的值默认存在数据库里
启用session
-
在setting中注册session应用(一般是默认添加的),并且添加中间件:
INSTALL_APP=[
...
'django.contrib.session',
]MIDDLEWARE_CLASSES=[
...
'django.contrib.sessions.middleware.SessionMiddleware',
]
session对象赋值(假字典)request.session['键']='值'
-
禁用会话:删除上面指定的两个值,禁用会话将节省一些性能消耗
使用session
- 启用会话后,每个HttpRequest对象将具有一个session属性,它是一个类字典对象
- get(key, default=None):根据键获取会话的值
- clear():清除所有会话
- flush():删除当前的会话数据并删除会话的Cookie
- del request.session['member_id']:删除会话
- 让我困惑的是,为什么使用了del删除会话信息,session表中仍存在一个字段
- session依赖于cookie;每个cookie中都储存着一个sessionid,用于和服务器中的session信息进行匹配。
会话过期时间
- set_expiry(value):设置会话的超时时间
- 如果没有指定,则两个星期后过期
- 如果value是一个整数,会话将在values秒没有活动后过期
- 若果value是一个imedelta对象,会话将在当前时间加上这个指定的日期/时间过期
- 如果value为0,那么用户会话的Cookie将在用户的浏览器关闭时过期
- 如果value为None,那么会话永不过期
- 修改视图中login_handle函数,查看效果
def login_handle(request):
request.session['uname'] = request.POST['uname']
# request.session.set_expiry(10)
# request.session.set_expiry(timedelta(days=5))
# request.session.set_expiry(0)
# request.session.set_expiry(None)
return redirect(reverse('main:index'))
session存到了哪里去?如何更改?
- 存到了数据库中,我们可以更改;但是要更改session的引擎。它还可以存到不同的地方去。
- 使用存储会话的方式,可以使用settings.py的SESSION_ENGINE项指定
基于数据库的会话:这是django默认的会话存储方式,需要添加django.contrib.sessions到的INSTALLED_APPS设置中,运行manage.py migrate在数据库中安装会话表,可显示指定为
SESSION_ENGINE='django.contrib.sessions.backends.db'
基于缓存的会话:只存在本地内在中,如果丢失则不能找回,比数据库的方式读写更快
SESSION_ENGINE='django.contrib.sessions.backends.cache'
可以将缓存和数据库同时使用:优先从本地缓存中获取,如果没有则从数据库中获取
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
使用Redis缓存session
会话还支持文件、纯cookie、Memcached、Redis等方式存储,下面演示使用redis存储
安装包
pip install django-redis-sessions
修改settings中的配置,增加如下项
SESSION_ENGINE = 'redis_sessions.session'
SESSION_REDIS_HOST = 'localhost'
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 0
SESSION_REDIS_PASSWORD = ''
SESSION_REDIS_PREFIX = 'session'
详解url函数
Django url()可以接收四个参数,分别是两个必选参数:regex、view 和++两个可选参数++:kwargs、name,接下来详细介绍这四个参数。
- regex: 正则表达式,与之匹配的 URL 会执行对应的第二个参数 view。
- view: 用于执行与正则表达式匹配的 URL 请求。
- kwargs: 视图使用的字典类型的参数。
- name: 用来反向解析 URL。
值得一提的是:使用 django.http.HttpResponse() 来输出 "Hello World!"。(他可以解析html语言)该方式将数据与视图混合在一起,并不符合 Django 的 MVC 思想。
路由 (网络工程术语)
路由(routing)是指分组从源到目的地时,决定端到端路径的网络范围的进程 [1]。
路由是指路由器从一个接口上收到数据包,根据数据包的目的地址进行定向并转发到另一个接口的过程。
路由工作包含两个基本的动作:
1、确定最佳路径
2、通过网络传输信息
manage.py 项目管理器的相关操作
python manage.py runserver 0.0.0.0:8008(后面的声明端口是可变更的,默认为8000)
#将应用中的modles.py中的数据表信息迁移到本地数据库(在数据库建表)。
python manage.py makemigrations 生成迁移
python manage.py migrate 执行迁移
python manage.py flush 删除迁移
python manage.py shell 运行Shell:
python manage.py createsuperuser 创建超级用户
Django的 QuerySet 的属性
QuerySet 可以被构造,过滤,切片,做为参数传递,这些行为都不会对数据库进行操作。只要你查询的时候才真正的操作数据库。(更多相关: https://blog.csdn.net/com_ma/article/details/79113291)
manage.py 和 django-admin.py 的区别
manage.py 生成应用多了[auth]、[contenttypes]、[sessions]、[staticfiles]
(详情请参阅:https://blog.csdn.net/ldw220817/article/details/78575409)
视图配置与URL,部分参考于Djangobook2.0
动态内容(显示时间の源代码)
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
动态URL
from django.http import HttpResponse
import datetime
def hello(request):
return HttpResponse("Hello world")
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
Templates 模板
(部分参考于Djangobook2.0)
模板就是定义一些我们显示的内容,一个模板可以被多个视图(Views)使用。
-
包括两个内容:
- 静态html页面
- 动态插入内容部分(通过模板语言生成)
-
设置模板路径,在settings.py中:
TEMPLATES = [
DIR:[os.path.join(BASE_DIR,'templates)]
]模板引擎会按照顺序搜索DIR和APP_DIR两个列表中的路径,以查找模板文件。
-
在应用中也可以有templates目录。在什么时候使用它?除非这个应用有很高的移植性,并且打算移植。
-
Django模板语言-DTL(我猜是Django-Templates-Language):定义在django.templates包中
Django处理模板分为两个阶段:加载:读取文件的内容到内存,渲染:填坑?。
我很好奇课件末尾去除模板硬编码的内容是什么。
- 加载:根据给定的表示找到模板然后预处理,通常会将它编译好放在内存中(找模板)。
loader.get_template(template_name),返回一个Template对象
- 渲染:使用Context数据对模板插值并返回生成的字符串(渲染模板)。
浏览器无法之间解析DTL模板语言,需要我们在发给浏览器之前解析掉它。
Template对象的render(RequestContext)方法,使用context渲染模板
- 完整源码:
from django.template import loader, RequestContext
from django.http import HttpResponse
def index(request):
temp = loader.get_template('temtest/index.html')
context = RequestContext(request, {})
return HttpResponse(tem.render(context))
于是就有了快捷函数
- render_to_string('字符串')——它等同于Httpresponse。
- render()是渲染的意思,他会解析模板
render -渲染-是处理视图逻辑路径的,
换句话说,他直接从给templates中寻找文件
render(request,'模板',context)
关于render()的"全称":
from django.http import HttpResponse
from django.template import ReqestContext,loader
temp = loader.get_template('booktest/index.html')
return HttpResponse(temp.render())
#-----------以上-------------
它很长,所以有了render(),他接受三个参数,分别是request,模板路径,上下文管理器(字典类型,一般为context,也可以写作local()"全局选择",通常可以直接定义一个字典:如{'info':'Hi'})
- redriect -重定向-是处理资源定位符路径的(url路径)
简单来说,他直接执行在url中写入路径的动作,以配合新的业务逻辑层的视图函数,但却不能在templates文件夹中寻找诸如以html等后缀结尾的视图逻辑曾的,页面文件
模板语言DTL
包含:
- 变量
- 标签
- 过滤器
- 注释{# DTL内容或者html#}(只有这种方法才能注释掉代码,否则会报错)
- 模板继承:为了更好的可读性,应该在{% block 名称 %}{% endblock 名称%}中填上名称。
变量:
- 语法:
{{ variable}} <!--这里写变量名--!>
- 当模板引擎遇到一个变量,就将计算这个变量的值,然后将jie'guo'shu'chu
- 变量名只能由字母数字下划线组成(不能以下划线开头),和点组成
- 当遇到'.'时,模板的会按照下列顺序查询:
- 字典查询foor['bar']
- 属性或方法查询foo.bar
- 数字索引查询,foo[bar]
- 变量不存在,模板系统将插入''(空字符串)。
- 模板中调用方法时候,系统会自动加括号();同时不能传递参数。
- 更深层次的理解:model层只是映射,如果数据库中已存在(并且一一对应),那么就不用迁移,可以直接使用。没错:就是这样,直接使用。
- 所以结合遇到'.'时候的查询顺序,我可以打印表名:只需要在模型类中定义方法就好了。只能用get获取单个数据时候使用。
class BookInfo(models.Model):
...
def tableName():
return verbpse_name
'''
view: book=BookInfo.objects.all()
templates: {{book.tableName}}
'''
- for标签
{% for ... in ...%}
{% forloop.countrt %} {# 获取循环索引值 #}
{% forloop.countrt0 %} {# 从0开始获取循环索引值 #}
{% empty %} {# 若为空 #}
{% endfor %}
- if标签
{% if... %}
{% elif %}
{% else %}
{% endif %}
- 多行注释comment
{% comment %}
{% endcomment %}
- 反向解析url
{% url 'name' p1 p2 %}
{% comment %}这里的p1,p2是两个参数{% endcomment %}
- 跨站请求伪造攻击防护csrf_token
{% csrf_token %}{# 一般写在form表单中,保护表单中的数据 #}
- 布尔标签:and、or,and比or的优先级高
- block、extends:详见“模板继承”
- autoescape:详见“HTML转义”
反向解析
正向解析是给了一个地址我们通过正则去匹配URL的规则,而反向解析,是我们通过RUL去请求获得一个,生成一个地址.
过滤器
-
语法
-
判断是否能够整除
{{ 变量|divisibleby:'整数'}}
模板继承
模板继承就是找共同点,牢记继承的三层结构。让他影响你的思想,三层结构融为一体。
而且你一定要记住,可以跨层填坑(重写)。而且,子模版就是填坑,先填哪一个无所谓,只要填上就行。
- 有关学习克隆魔法的哲思:每一个学生在学习高阶克隆魔法之前,都应该学习三层继承结构,并且完成一个自己的页面作为作业交给自己的老师。
base:
base_user:
user_Center,user_Address
base_good:
good_list,good_show
模板是一个文本,用于分离文档的表现形式和内容。模板通常用于产生HTML,但是Django的模板也能产生任何基于文本格式的文档。这些功能非常COOL。
用两个大括号括起来的文字(例如 {{ person_name }} )称为 变量(variable) 。
被大括号和百分号包围的文本(例如 {% if ordered_warranty %} )是 模板标签(template tag) 。标签(tag)定义比较明确,即: 仅通知模板系统完成某些工作的标签。
有一个关于filter过滤器的例子,它是一种最便捷的转换变量输出格式的方式。如这个例子中的{{ship_date|date:”F j, Y” }}
在Python代码中使用Django模板的最基本方式如下:
可以用原始的模板代码字符串创建一个 Template 对象, Django同样支持用指定模板文件路径的方式来创建 Template 对象;
调用模板对象的render方法,并且传入一套变量context。它将返回一个基于模板的展现字符串,模板中的变量和标签会被context值替换。
在模板文件中书写模板语言
>><h1>{{ HELLO }} </h1>
向Django说明模板文件的路径;全局配置文件: Setting.py
TEMPLATES = [
...
'DIRS': [BASE_DIR+"/templates",], # 修改位置
#'DIRS': [os.path.join(BASE_DIR+"/templates",)], #或是写成这样
...
]
增加新对象,向模板提交数据:视图文件 views.py
#coding=utf-8
#from django.http import HttpResponse
from django.shortcuts import render
def hello(request):
context = {}
context['hello'] = 'Hello World!'
return render(request, 'hello.html', context)
#return render(request, 'hello.html',{'HELLO':'这里必须写一个相对应的键值对'})
我们这里使用 render 来替代之前使用的 HttpResponse 对页面进行渲染。值得一提的是,HttpResponse()不能将渲染的形式和和内容分离。不符合MVT的设计思维。
context 字典中元素的键值 "hello" 对应了模板中的变量 "{{ hello }}"。
----------------后台管理--------------------
内容发布 和 公共访问。
│
└─管理员:增删改查数据
当初做的很多东西让我觉得困惑。可我已经掌握了如何搭建Django项目,现在想来,只需要该一条HttpResponse响应语句就可以了。
项目创建需要注意的一点是:
有过 PHP 编程背景的话,你可能习惯于将代码都放在 Web 服务器的文档根目录 (例如 /var/www 这样的地方)。而在 Django 中,你不能这样做。把任何 Python 代码放到 Web 服务器的文档根目录中都不是个好主意,因为这样一来,你就要冒着别人透过页面直接看到代码的风险。这对于安全可不是件好事。把代码放置在文档根目录之外的某些目录中。
admin后台站点管理工具
(部分参考Djangobook2.0第六章)
++管理界面++是某一类网站基础设施中非常重要的一部分,所以我们今天学习++Django的自动管理管理页面++。
他的特性是:
从模型中读取元数据,把他加载到到一个强大的管理页面中,提供给网站管理者使用。
(请注意我们建议你读这章,即使你不打算用admin。因为我们将介绍一些概念,这些概念可以应用到Django的所有方面,而不仅仅是admin)
- 梗概:使用步骤
- 本地化管理界面(更改语言)
- 创建管理员
- 注册模型类
- 发布内容到数据库
- 自定义站点管理界面
概念:django.contrib 包
Django管理工具是它的一部分,django.contrib是一套庞大的功能集。
(它是Django基本代码的组成部分,Django框架就是由众多包含附加组件(add-on)的基本代码构成的。)
目前我们只需要知道Django自带很多优秀的附加组件,它们都存在于django.contrib包里,如:
用户鉴别系统(django.contrib.auth)、
支持匿名会话(django.contrib.sessioins)
以及用户评注系统(django.contrib.comments)。
搭建步骤:
1.激活管理工具:
[INSTALLED_APPS:]
确保包含这四个应用的存在:
'django.contrib.admin'
'django.contrib.auth'
'django.contrib.contenttypes'
'django.contrib.sessions'
[MIDDLEWARE_CLASSES:]
含'django.middleware.common.CommonMiddleware' 'django.contrib.sessions.middleware.SessionMiddleware'
'django.contrib.auth.middleware.AuthenticationMiddleware'
2.接下来进行数据库迁移(历史版本syncdb)
我们还需要一个管理员,这个时候我们创建一个超级用户:
就需要运行这个命令 python manage.py createsuperuser,
输入用户名和密码,邮箱不是必填的。
(++值得一提的是:这命令是属于'django.contrib.auth'这个模块的++)
3.然后我们把它填写到URL路由中。
需要确保from django.contrib import admin (后台管理模块)已经被导入。
[URL]:>urlpatterns:
++url(r'^admin/', include(admin.site.urls)),++
4.更改语言,使用admin管理工具
完成以上一系列配置之后,运行python manage.py runserver命令启动服务器。
(界面管理的设计是针对非技术人员的,所以它是自我解释的。)
所以我们应该去setting中,可以把管理界面相关的语言改成我们自己国家使用的语言,就比如中文的话:
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False
admin注册模型类:admin.site.register
我们++需要管理其他的表++,需要将其他的表添加到后台管理工具中,++在admin.py中注++册它。
概念:在Django管理页面中,每一种数据类型都有一个 change list 和 edit form 。
(前者显示数据库中所有的可用对象;后者可让你添加、更改和删除数据库中的某条记录。)
管理界面就是一个漂亮的表查询和表操作界面,但每一条更改都会被记录到历史信息中。
在没有添加应用、并且没有在应用中添加models模型表的时候,我们进行数据库迁移是不需要python manage.py makemigrations(生成迁移)这条命令的,如果使用一下我们就能看到系统的提示:No changes detected
(数据没有更改)
admin.site.register 接受一个ModelAdmin子类作为可选参数。用于控制模型类的显示方式。
自定义admin列表步骤> [admin.py:] - ModelAdmin是admin的子类
- 建立类
class AuthorAdmin(admin.ModelAdmin):
- 添加方法:
#例如:
list_display=('name','email','country')
(包含字段名称的元组)
- 作为参数被注册
admin.site.register(Author,AuthorAdmin)
(以上操作不对数据库造成更改)
自定义admin列表工具集[admin.py:]
--(管理界面不应允许公众访问和复杂排序,查询;且仅提供给可信任的管理员)--
显示指定字段
list_display=('name','email','country')
#接收包含字段名称的元组
- 添加根据姓名查询的查询框
search_fields=("name")
'''对大小写敏感,且默认不支持外键
[解决办法]:字段名+双下划线+属性名,例如:
search_field=('author_name')
'''
- 根据作者、时间查询的过滤器
list_filter("author","time")
#支持布尔型,外键,多个字段
- 添加一个时间导航条
date_hierarchy='time'
只支持时间类型的字段
- 添加排序
ordering=("-time","name")
#通过时间来排序name
#只支持元祖类型参数
- 改变字段的排列顺序
fields=("time","name")
'''他可以用来开放/关闭可编辑的字段,只需要不填写即可,同时:
系统会将他设置为None(必须符合null=True约束)
目前为止,除了搜索栏,其他都支持外键'''
- 内联(或称关联)
#----编辑和添加页面的效果,它更复杂一些-----
#1.创建连接类(表格效果)
class BookInline(admin.TabularInline):
model=Book #(外键表名)
extra = 3 #(限制可更改属性的数量上限)
#2.在管理类中创建连接
classAuthorAdmin(admin.ModelAdmin):
**lines=[BookInlines]** #主要是这一步,但两步缺一不可
#还有第二种实现方法,但实现效果有略微区别,我们需要改为继承停靠方法
#1.创建连接类
class BookInline(admin.StackedInline):
model=Book #(外键表名)
extra = 3 #(限制属性的数量上限)
#2.在管理类中创建连接
classAuthorAdmin(admin.ModelAdmin):
**lines=[BookInlines]**
#除了类名和显示效果略微不同外,其他使用效果完全相同
- 下侧分页
list_per_page = 1
# 一页只显示1条数据
- 将属性分组
# ----应用于添加页面和管理页面的效果----
# 主要是一个json格式看起来更复杂
# 他的键名是可以自定义的,你可以随便定义键名用作组名
fieldsets = [
('basic',{'field':['btitle']}),
('more',{'field':['bpub_date']}),
]
- 属性的先后顺序
# ----应用于添加页面和管理页面的效果-----
field = ['bpub_date','btitle']
表单
(部分参考于Djangobook2.0第七章)
从Google的简朴的单个搜索框,到常见的Blog评论提交表单,再到复杂的自定义数据输入接口,HTML表单一直是交互性网站的支柱。 本章介绍如何用Django对用户通过表单提交的数据进行访问、有效性检查以及其它处理。 与此同时,我们将介绍++HttpRequest对象++和++Form对象++。
HttpRequest对象包含当前请求URL的一些信息:
属性/方法 说明 举例
request.path 除域名以外的请求路径,以正斜杠开头 "/hello/"
request.get_host() 主机名(比如,通常所说的域名) "127.0.0.1:8000" or "www.example.com"
request.get_full_path() 请求路径,可能包含查询字符串 "/hello/?print=true"
request.is_secure() 如果通过HTTPS访问,则此方法返回True, 否则返回False True 或者 False
request.META
request.META 是一个Python字典,包含了所有本次HTTP请求的Header信息,比如用户IP地址和用户Agent(通常是浏览器的名称和版本号)。
以下是常见的键值:
HTTP_REFERER,进站前链接网页,如果有的话。 (请注意,它是REFERRER的笔误。)
11
HTTP_USER_AGENT,用户浏览器的user-agent字符串,如果有的话。 例如: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17" .
REMOTE_ADDR 客户端IP,如:"12.345.67.89" 。(如果申请是经过代理服务器的话,那么它可能是以逗号分割的多个IP地址,如:"12.345.67.89,23.456.78.90" 。)
值得一提的是:注意,因为 request.META 是一个普通的Python字典,因此当你试图访问一个不存在的键时,会触发一个KeyError异常。 (HTTP header信息是由用户的浏览器所提交的、不应该给予信任的“额外”数据,因此你总是应该好好设计你的应用以便当一个特定的Header数据不存在时,给出一个优雅的回应。)你应该用 ++try/except++ 语句,++或者用Python字典的 get() 方法++来处理这些“可能不存在的键”
- 今天总结了几个写登陆注册时候的注意事项,这是我常常忽略的。我经常忘记在input输入框外面套form(表单)标签。————总结下原因,其实是自己对于内部运行机制的掌握不熟练所致的。
- 第二个常犯的错误就是总是忘记在form(post请求方式)标签内添加{% csrf_token%,导致服务器运行起来的时候,浏览器会返回403错误。
- 第三个出现的错误就是,会遗忘在运行服务器之前把数据库迁移,导致注册页面的信息无法导入数据库。下次迁移记得加。爱你。
Django的认证系统
Django认证系统,包含了身份验证和权限管理两部分。简单地说,身份验证用于核实某个用户是否合法,权限管理则是决定一个合法用户具有哪些权限。往后,‘认证’这个词同时代指上面两部分的含义。
一、用户与分组-User & Group
- 创建用户:
from django.contrib.auth.models import User
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
user = User.objects.create_user(username="zhaoyingwei",password="123")
return HttpResponse('用户创建成功')
- 修改密码:
def index(request):
u = User.objects.get(username='python')
u.set_password('321')
return HttpResponse('密码修改成功')
- 用户验证:
from django.contrib.auth import authenticate
def index(request):
user = authenticate(username='python', password='321')
if user:
return HttpResponse('验证通过')
- 组的创建:
#coding=utf-8
from django.contrib.auth.models import Group
from django.contrib.auth.models import User
def index(request):
group = Group.objects.create(name=group_name)
group.save()
return HttpResponse('组创建成功')
- 用户添加到组:
def index(request):
group = Group.objects.get(name = '第一组')
user = User.objects.get(username="zhaoyingwei", password="123")
user.groups.add(group)
return HttpResponse('ok')
- 用户加入用户组
user.groups.add(group)
group.user_set.add(user)
- 用户退出用户组
user.groups.remove(group)
group.user_set.remove(user)
- 用户退出所有用户组
user.groups.clear()
- 用户组中所有用户退出组
group.user_set.clear()
- 登录
login向session中添加SESSION_KEY, 便于对用户进行跟踪:
login不进行认证,也不检查is_active标志位, 一般和authenticate配合使用:
from django.contrib.auth import login
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
在auth/__init__.py中可以看到login的源代码。
- 退出登录
logout会移除request中的user信息, 并刷新session:
from django.contrib.auth import logout
def logout_view(request):
logout(request)
- 权限判断,只允许登录用户访问
@login_required修饰器修饰的view函数会先通过session key检查是否登录,
已登录用户可以正常的执行操作, 未登录用户将被重定向到login_url指定的位置。
若未指定login_url参数, 则重定向到settings.LOGIN_URL。
from django.contrib.auth.decorators import login_required
@login_required(login_url='/accounts/login/')
def my_view(request):
二、权限-Permission
Django的auth系统提供了模型级的权限控制,
即可以检查用户是否对某个数据表拥有增(add), 改(change), 删(delete)权限。
-
auth系统无法提供对象级的权限控制,即检查用户是否对数据表中某条记录拥有增改删的权限。
假设:在博客系统中有一张article数据表管理博文,
auth可以检查某个用户是否拥有对所有博文的管理权限,
但无法检查用户对某一篇博文是否拥有管理权限。 -
如果需要对象级权限控制可以使用django-guardian。
-
检查用户权限:
user.has_perm方法用于检查用户是否拥有操作某个模型的权限:
user.has_perm('blog.add_article')
user.has_perm('blog.change_article')
user.has_perm('blog.delete_article')
'''上述语句检查用户是否拥有blog这个app中article模型的添加权限, 若拥有权限则返回True。
has_perm仅是进行权限检查, 即是用户没有权限它也不会阻止程序员执行相关操作。而且无关于该用户是否离职。'''
示例:
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
def index(request):
user = authenticate(username='lucy', password='123')
if user.has_perm('booktest.add_bookinfo'):
return HttpResponse('用户拥有这个权限')
else:
return HttpResponse('没有权限')
from django.contrib.auth import authenticate
from django.contrib.auth.models import Permission, User
def index(request):
Permission.objects.create(name='角色管理',content_type_id=7,codename='权限管理描述')
perm = Permission.objects.get(name='角色管理')
User.objects.get(username='zhaoyingwei').user_permissions.add(perm)
return HttpResponse('ok')
@permission_required装饰器
- 可以代替has_perm并在用户没有相应权限时重定向到登录页或者抛出异常。
- 每个模型默认拥有增(add), 改(change), 删(delete)权限。
- 在django.contrib.auth.models.Permission模型中保存了项目中所有权限。
该模型在数据库中被保存为auth_permission数据表。
permission_required(perm[, login_url=None, raise_exception=False])
@permission_required('blog.add_article')
def post_article(request):
pass
- 管理用户权限
User和Permission通过多对多字段user.user_permissions关联,
在数据库中由auth_user_user_permissions数据表维护。
- 添加权限
user.user_permissions.add(permission)
- 删除权限:
user.user_permissions.delete(permission)
- 清空权限:
用户拥有他所在用户组的权限, 使用用户组管理权限是一个更方便的方法。
Group中包含多对多字段permissions, 在数据库中由auth_group_permissions数据表维护。
user.user_permissions.clear()
- 添加权限:
group.permissions.add(permission)
- 删除权限:
group.permissions.delete(permission)
- 清空权限:
group.permissions.clear()
- 自定义权限:
在定义Model时可以使用Meta自定义权限:
class Discussion(models.Model):
...
class Meta:
permissions = (
("create_discussion", "Can create a discussion"),
("reply_discussion", "Can reply discussion"),
)
- 判断用户是否拥有自定义权限:
user.has_perm('blog.create_discussion')
- 添加权限:
Permission.objects.create(name=u'权限管理',content_type_id=2,codename=u'权限管理描述')
- 添加用户权限:
perm = Permission.objects.get(codename=u'权限管理')#首先你需要添加"权限管理"这项权限
User.objects.get(username='270001').user_permissions.add(perm)
- 删除用户权限:
perm = Permission.objects.get(codename=u'权限管理')#首先你需要添加"权限管理"这项权限
User.objects.get(username='270001').user_permissions.remove(perm)
- 批量添加用户权限:
perm1 = Permission.objects.get(codename=u'权限管理')
perm2 = Permission.objects.get(codename=u'用户管理')
User.objects.get(username='270001').user_permissions.add(perm1,perm2)
- 清空用户权限:
User.objects.get(username='270001').user_permissions.clear()
- 查询用户权限,并输出
c = User.objects.get(username='270001').user_permissions.values()
for i in c:
print i
分页系统 Paginator
- Django提供了一个新的类来帮助你管理分页数据,这个类存放在django/core/paginator.py.它可以接收列表、元组或其它可迭代的对象。
#源码
class Paginator(object):
def __init__(self, object_list, per_page, orphans=0,
allow_empty_first_page=True):
self.object_list = object_list
self._check_object_list_is_ordered()
self.per_page = int(per_page)
self.orphans = int(orphans)
self.allow_empty_first_page = allow_empty_first_page
- 实例:
- 生成对象前导入模块
from django.core.paginator import Paginator
objects = ['a','b','c','d','e','f','g','h','i','j']
- 实例化分页对象:以3为距离单位切割对象(仍保留全部完整数据)
p = Paginator(objects,3)
- 查看对象元素总数(10个)
p.count
- 查看对象分成了几页(4页)
p.num_pages
- 查看对象的可迭代范围
p.page_range
#这里返回:xrange(1,5)
- 取对象的第一分页对象
page1 = p.page(1)
# 我这里输出:<Page 1 of 10>
- 第一分页对象的元素列表['john', 'paul', 'george']
page1.object_list
#这里返回:['a', 'b', 'c']
- 第一分页对象的当前页值 1
page1.number
- 分页对象是否有前一页
page1.has_previous()
#False
- 分页对象是否有下一页
page1.has_next()
#Ture
- 对象是否有其它页
page1.has_other_pages()
#True
- 分页对象下一页码的值
page1.next_page_number()
- 分页对象的上一页码值
page1.previous_page_number()
- 分页对象的元素开始索引
page2.start_index()
- 分页对象的元素结束索引
page2.end_index()
- 模板系统会为我们自动添加函数后面的括号,比如让我很困惑的page1.has_previous 和 page1.has_previous()
数据格式json(data.json)
- json是一个数据格式:全称JavaScript Object Notation (Js对象表示)
- json与XML:json在逐渐取代XML
json格式数据:
{
"name":'tom',
"age":18
"info":["male","engineer"]
}
与json对象不同的是,json数据格式的属性名称(Key)需要用双引号引起来,用单引号或者不用引号会导致读取数据错误。
json的另外一个数据格式是数组,和javascript中的数组字面量相同。
['tom',18,'programmer']
ajax与jsonp
ajax的目的是让JavaScript发送http请求,与后台通信,获取数据和信息
ajax是被吹上天了的一个技术,让人看看不清它的本质。
同步与异步
程序中的同步和异步与现实生活中的同步和异步是对调的。异步是可以同时做几件事情。
局部刷新与无刷新
ajax可以是实现局部刷新,也叫做无刷新。无刷新
同源策略
ajax为了安全性的需要,它只能请求同一个域下面或组域和子域的内容。例如阿里的ajax不能请求腾讯的数据。
(在服务器环境里才能读)
admin后台站点管理工具,部分参考Djangobook2.0第六章
++管理界面++是某一类网站基础设施中非常重要的一部分,所以我们今天学习++Django的自动管理管理页面++。
他的特性是:
从模型中读取元数据,把他加载到到一个强大的管理页面中,提供给网站管理者使用。
(请注意我们建议你读这章,即使你不打算用admin。因为我们将介绍一些概念,这些概念可以应用到Django的所有方面,而不仅仅是admin)
梗概:使用步骤
- 本地化管理界面(更改语言)
- 创建管理员
- 注册模型类
- 发布内容到数据库
- 自定义站点管理界面
概念:django.contrib 包
Django管理工具是它的一部分,django.contrib是一套庞大的功能集。
(它是Django基本代码的组成部分,Django框架就是由众多包含附加组件(add-on)的基本代码构成的。)
目前我们只需要知道Django自带很多优秀的附加组件,它们都存在于django.contrib包里,如:
用户鉴别系统(django.contrib.auth)、
支持匿名会话(django.contrib.sessioins)
以及用户评注系统(django.contrib.comments)。
搭建步骤:
1.激活管理工具:
[INSTALLED_APPS:]
确保包含这四个应用的存在:
'django.contrib.admin'
'django.contrib.auth'
'django.contrib.contenttypes'
'django.contrib.sessions'
[MIDDLEWARE_CLASSES:]
含'django.middleware.common.CommonMiddleware' 'django.contrib.sessions.middleware.SessionMiddleware'
'django.contrib.auth.middleware.AuthenticationMiddleware'
2.接下来进行数据库迁移(历史版本syncdb,不再赘述)
但是我们还需要一个管理员,这个时候我们创建一个超级用户:
我们就需要运行这个命令 python manage.py createsuperuser,
输入用户名和密码,邮箱不是必填的。
(++值得一提的是:这命令是属于'django.contrib.auth'这个模块的++)
3.然后我们把它填写到URL路由中。
需要确保from django.contrib import admin (后台管理模块)已经被导入。
[URL]:>urlpatterns:
++url(r'^admin/', include(admin.site.urls)),++
4.更改语言,使用admin管理工具
完成以上一系列配置之后,运行python manage.py runserver命令启动服务器。
(界面管理的设计是针对非技术人员的,所以它是自我解释的。)
所以我们应该去setting中,可以把管理界面相关的语言改成我们自己国家使用的语言,就比如中文的话:
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False
admin注册模型类:admin.site.register
我们++需要管理其他的表++,需要将其他的表添加到后台管理工具中,++在admin.py中注++册它。
概念:在Django管理页面中,每一种数据类型都有一个 change list 和 edit form 。
(前者显示数据库中所有的可用对象;后者可让你添加、更改和删除数据库中的某条记录。)
管理界面就是一个漂亮的表查询和表操作界面,但每一条更改都会被记录到历史信息中。
在没有添加应用、并且没有在应用中添加models模型表的时候,我们进行数据库迁移是不需要python manage.py makemigrations(生成迁移)这条命令的,如果使用一下我们就能看到系统的提示:No changes detected
(数据没有更改)
admin.site.register 接受一个ModelAdmin子类作为可选参数。用于控制模型类的显示方式。
自定义admin列表步骤> [admin.py:] - ModelAdmin是admin的子类
- 建立类
class AuthorAdmin(admin.ModelAdmin):
- 添加方法:
#例如:
list_display=('name','email','country')
(包含字段名称的元组)
- 作为参数被注册
admin.site.register(Author,AuthorAdmin)
(以上操作不对数据库造成更改)
自定义admin列表工具集[admin.py:]
--(管理界面不应允许公众访问和复杂排序,查询;且仅提供给可信任的管理员)--显示指定字段
list_display=('name','email','country')
#接收包含字段名称的元组
添加根据姓名查询的查询框
search_fields=("name")
'''对大小写敏感,且默认不支持外键
[解决办法]:字段名+双下划线+属性名,例如:
search_field=('author_name')
'''
根据作者、时间查询的过滤器
list_filter("author","time")
#支持布尔型,外键,多个字段
添加一个时间导航条
date_hierarchy='time'
只支持时间类型的字段
添加排序
ordering=("-time","name")
#通过时间来排序name
#只支持元祖类型参数
改变字段的排列顺序
fields=("time","name")
'''他可以用来开放/关闭可编辑的字段,只需要不填写即可,同时:
系统会将他设置为None(必须符合null=True约束)
目前为止,除了搜索栏,其他都支持外键'''
内联
#在编辑页面的效果,它更复杂一些
#1.创建连接类
class BookInline(admin.TabularInline):
model=Book #(外键表名)
#2.在管理类中创建连接
classAuthorAdmin(admin.ModelAdmin):
**lines=[BookInlines]** #主要是这一步,但两步缺一不可
百科:
URL
URL(统一资源定位符)全称是UniformResourceLocator,是互联网上用来标识某一处资源的地址。
包含了用于查找某个资源的足够的信息。 URL分为七个部分:
(详解URL组成原文:http://blog.csdn.net/ergouge/1article/details/8185219 )
1.协议 2.域名 3.端口 4.虚拟目录 5.文件名 6.锚 7.参数
触发出错:
assert False 来触发出错页。 然后,你就可以看到局部变量和程序语句了。
(__name__
:意为当前目录。)
Markdown:
- Markdown可以解析前端标签。我刚才打算展示前端页面的源代码,少写了一个回车,他居然直接给我渲染出来了。
CBV与FBV:
- 分别是基于类的视图和基于函数的视图。
什么是 BSD 协议?
BSD开源协议是一个给于使用者很大自由的协议。可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布。当你发布使用了BSD协议的代码,或者以BSD协议代码为基础做二次开发自己的产品时,需要满足三个条件:
如果再发布的产品中包含源代码,则在源代码中必须带有原来代码中的BSD协议。
如果再发布的只是二进制类库/软件,则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议。
不可以用开源代码的作者/机构名字和原来产品的名字做市场推广。
BSD代码鼓励代码共享,但需要尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码,也允许使用或在BSD代码上开发商业软件发布和销 售,因此是对商业集成很友好的协议。
很多的公司企业在选用开源产品的时候都首选BSD协议,因为可以完全控制这些第三方的代码,在必要的时候可以修改或者 二次开发。
在pycharm中配置端口
render的参数local():
- 鲁莽选择(它会选择函数中所有的字段全部传到前端)
has_key()函数的使用:
- 在python3中已经移除该方法,改用in来查询字典是否拥有某个键值。
一些创建数据模型的参考:
- 书籍:标题(book_title),出版时间(book_pub_date),阅读量(b_read),书籍信息(book_comment),逻辑删除(isDelete)
- 英雄:姓名(hero_name),性别(hero_gender),描述()
通用视图
切勿退出装饰器
│命名空间
一些假数据(用于测试):
- 模型BookInfo的测试数据
insert into book(b_title,b_pub_date,b_read,b_commet,isDelete) values
('射雕英雄传','1980-5-1',12,34,0),
('天龙八部','1986-7-24',36,40,0),
('笑傲江湖','1995-12-24',20,80,0),
('雪山飞狐','1987-11-11',58,24,0);
- 模型HeroInfo的测试数据
insert into modelapp_heroinfo(h_name,h_gender,h_book_id,h_content,isDelete) values
('郭靖',1,1,'降龙十八掌',0),
('黄蓉',0,1,'打狗棍法',0),
('黄药师',1,1,'弹指神通',0),
('欧阳锋',1,1,'蛤蟆功',0),
('梅超风',0,1,'九阴白骨爪',0),
('乔峰',1,2,'降龙十八掌',0),
('段誉',1,2,'六脉神剑',0),
('虚竹',1,2,'天山六阳掌',0),
('王语嫣',0,2,'神仙姐姐',0),
('令狐冲',1,3,'独孤九剑',0),
('任盈盈',0,3,'弹琴',0),
('岳不群',1,3,'华山剑法',0),
('东方不败',0,3,'葵花宝典',0),
('胡斐',1,4,'胡家刀法',0),
('苗若兰',0,4,'黄衣',0),
('程灵素',0,4,'医术',0),
('袁紫衣',0,4,'六合拳',0)
学习Django内部原理笔记
在这里安装过的应用,本质其实都是对Python包的引入。我们都可以在目录中找到这些应用的位置。
看一下,就是这个socail_dango也是可以找到的。(它是第三方包)
这里的social_core
并没有在应用中安装。
今天我误把AUTHENTICATION_BACKENDS当作了中间件,直到它报了很多错误。我才发现我的
social_core.backends.weibo.Weibo
不应该放在MIDDLEWARE
配置列表中。但是我学习了很多中间件的知识:
其实配置中间件的本质也就是通过访问文件夹路径来引入Python包中的一个个中间件,也就是类。(它们就是用于提供各种各样的特殊的功能)。
日志管理
第三方登录
Celery异步加载首先需要安装第三方协程包
操作系统:win10
- 安装Celery
pip install celery
- windows需要安装第三方协程包
pip install eventlet
- 建立一个
task.py
文件
这个文件会被celery添加到任务队列中,当调用该文件的命令信号发送到celery时,该文件的内容会被执行。
同时,当需要其他的异步功能时,可以再写新的py脚本,将他们都添加到任务队列中。
位置:项目下/Celery_tasks/task.py
from celery import Celery
import os
broker_url = "redis://127.0.0.1:6379/14"
result_backend = "redis://127.0.0.1:6379/15"
app = Celery('tasks', broker=broker_url, backend=result_backend)
from yunpian_python_sdk.model import constant as YC
from yunpian_python_sdk.ypclient import YunpianClient
apikey = '846bd5453a038f21d779130c672046b0'
@app.task(name='send_sms_code') # 给任务取一个名字,一般就是函数名字
def send_sms_code(mobile, sms_code):
clnt = YunpianClient(apikey)
param = {YC.MOBILE: mobile, YC.TEXT: '【云片网】您的验证码是%s' % sms_code}
r = clnt.sms().single_send(param)
print(r.code(), r.data())
- 启用celery
使用命令调用该文件,将其添加到任务队列。
enventlet 就是刚才我们安装的windows协程包。
将它交给运行器(worker)来等待处理。
Celery -A ./celery/task worker -l info -P eventlet
成功的运行结果
什么时候触发运行?
当celery被我们开启之后,它会一直等待消息命令的传入,也就是说,这是可以多次触发,多次运行的。
- 在Views中这样写:
from celery_tasks.tasks import send_sms_code
send_sms_code.delay(mobile, sms_code) # 使用celery异步任务发送短信
- 上一张配图
电商中什么是SPU 和SKU?
在电商中对于商品,有两个重要的概念:SPU和SKU
先看一段非常长的介绍
- SPU = Standard Product Unit (标准产品单位)
SPU是商品信息聚合的最⼩小单位,是⼀一组可服⽤用、易易检索的标
准化信息的集合,该集合描述了了⼀一个产品的特性。
通俗的讲,属性值、特性相同的商品就可以称为⼀一个SPU。
例例如:
iPhone X 就是⼀一个SPU,与商家、颜⾊色、款式、规格、套餐等
都⽆无关。
- SKU = Stock Keeping Unit (库存量量单位)
SKU即库存进出计量量的单位,可以是以件、盒、托盘等为单位,
是物理理上不不可分割的最⼩小存货单元。在使⽤用时要根据不不同业态,
不不同管理理模式来处理理。在服装、鞋类商品中使⽤用最多最普遍。
例例如:
iPhone X 全⽹网通⿊黑⾊色256G 就是⼀一个SKU,表示了了具体的规
格、颜⾊色等信息。
相信大家看完了刚才的介绍,肯定还是蒙的,你说的这是啥?
没关系,不用看刚才那两段话也能明白这两个概念。
还有两个图供大家选择:第一个图适合未成年人观看。
第二个图也适合未成年人观看。我自己画的,丑但是很容易懂。
CKEditor 富文本编辑器
使用圣堂法术DRF进行接口开发
链接:点击这里就不会错过青魔法圣堂法术 DRF (Django REST framework) 框架(持续更新)
链接:更多请关注我的青魔法Python
——向前走吧,往往最珍贵的东西都不容易在表层浮现的事物找到。