Django

一、Django 简介

  Django 是一个是因为 Python 写成的开放源代码的 Web
应用框架。它最初是叫出来用于管理劳伦斯出版集团西下之片坐新闻内容为主的网站的,即凡
CMS(内容管理网)软件。并让2005年7月当 BSD
许可证下发布。这套框架是盖比利时底吉普赛爵士吉他手 Django Reinhardt
来命名的。由于 Django
的是于一个赶紧节奏的情报编辑室环境下开的,它的目的是要周边的 Web
开发任务,快速和爱。

 

MTV 模式

Django 采用了 MTV 设计模式

bifa365必发 1

上述图大概是说:

  1. URL ( urls.py )请求调度,当起缓存页面的时节一直返回内容。
  2. 目图函数( view.py )执行所要的操作,通常包括读写数据库。
  3. 范( models.py )定义了 Python
    中的多寡并与的并行。通常含在一个关系数据库( MySQL、PostgreSQL
    SQLite 等),其他数存储是可能的( XML、文本文件、LDAP、等)。
  4. 求执行任务后,视图返回一个 HTTP
    响应对象(通常是经过多少处理的一个模板)。可选的:视图可以保存一个版本的
    HTTP 响应对象,返回携带一个时刻戳,来喻浏览器是视图的换代时间。
  5. 模板通常返回 HTML 页面。Django 模板语言提供了 HTML 的语法及逻辑。

 bifa365必发 2

 

 安装

# pip 安装
pip install Django==1.10

# 克隆下载最新版本
git clone https://github.com/django/django.git

# 导入django模块
>>> import django
>>> print(django.get_version())
1.10

 

第二、基本配备

1、常用命令

# 查看django版本
$ python -m django --version

# 创建项目,名为mysite
$ django-admin startproject mysite

# 启动django
$ python manage.py runserver
$ python manage.py runserver 8080
$ python manage.py runserver 0.0.0.0:8000

# 创建应用程序,确保和 manage.py 是同一目录
$ python manage.py startapp polls

# 运行创造模型变化迁移
$ python manage.py makemigrations

# 运行应用模型变化到数据库
$ python manage.py migrate

# admin创建管理员用户
$ python manage.py createsuperuser

注:自动还加载 runserver,根据需要支付服务器自动重新加载Python代码为每个请求。您不需更起动服务器代码更改生效。然而,像长文件某些操作不接触重新开动,所以您不能不还起动于这些状况下之服务器。

中心目录结构及作用:

mysite/              # 项目的容器,名字随便起
    manage.py        # 命令行实用工具,以各种方式与该Django项目进行交互
    mysite/          # 实际的Python项目
        __init__.py  # 空文件,导入不出错
        settings.py  # 这个Django项目配置
        urls.py      # 这个Django项目的URL声明; 一个Django驱动网站的“目录”
        wsgi.py      # 一个入口点为WSGI兼容的Web服务器,以满足您的项目

 

 2、配置文件

数据库

# 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替

# 如下设置放置的与project同名的配置的 __init__.py文件中

import pymysql
pymysql.install_as_MySQLdb() 

# 在settings 中修改DATABASES 

DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME':'dbname',
    'USER': 'root',
    'PASSWORD': 'xxx',
    'HOST': '',
    'PORT': '',
    }
}

模板 

# 也在settings里修改,放html文件

TEMPLATE_DIRS = (
        os.path.join(BASE_DIR,'templates'),
    )

 静态文件

# 依然在settings里修改添加,放css,js等文件

STATICFILES_DIRS = (
        os.path.join(BASE_DIR,'static'),
    )

 

 三、路由于网

1、URL 调度

一个完完全全,优雅的 URL 方案是一个大质量之 Web 应用程序的一个要的细节。

与 tornado 不同之是一个
url 对应一个函数,而不要一个类似。

如是一个新华字典的目,对承诺了 views 函数来展开拍卖,即是 url
要为此有指定的 views 函数处理。

来拘禁以下示例,如何动态构造:

from app1 import views

urlpatterns = [
    url(r'^manage1/(\d*)', views.manage1),
    url(r'^manage2/(?P<name>\w*)/(?P<id>\d*)', views.manage2),
    url(r'^manage3/(?P<name>\w*)', views.manage3,{'id':333}),
]

# 需要注意
# url多传了一个参数,那views函数得多接受一个参数 

bifa365必发 3bifa365必发 4

# 对应接收值

def manage1(request, age):
    print(age)        # 18
    return HttpResponse('1')

def manage2(request, name, id):
    print(name, id)     # nick 18
    return HttpResponse('2')

def manage3(request, name, id):
    print(name, id)     # nick 666
    return HttpResponse('3')

针对许 views 函数接收值

 

二级路由于: 这就是说若照 url 太多庸惩罚,全写一个在  urlpatterns
显得繁琐,so 二级路由于运用而分外

# 一级路由规定 app1 开头的都去 app1.urls 中找
# 二级在详细规定对应 views 函数

# 一级
urlpatterns = [
    url(r'^app1/', include('app1.urls')),
]

# 二级
urlpatterns = [
    url(r'^1$', views.manage1),
]

 

2、Django是怎处理一个请

当用户要于君的 Django 的网站页面,这是欠体系以以确定如何 Python
代码执行的算法:

  1. Django 请求是 URL 配置模块配置。通常通过值 ROOT_URLCONF 设置,但只要传入 HttpRequest 对象有 urlconf 属性(由中件装),它的价将顶替的可利用
     ROOT_URLCONF 的设置。
  2. Django 的载重是 Python 模块并查找变量 urlpatterns。这是一个 django.conf.urls.url() 实例。
  3. Django 的贯通每个 URL 模式,从而,在所要的 URL 匹配的第一单已。
  4. 若某个正则表达式相配合,就运行相对应之视图函数(或根据类的视图)。该视图给传送以下参数:
    • HttpRequest 对象。
    • 而匹配的正则表达式没有回来命名组,然后由正则表达式比赛是当职务参数。
    • 主要词参数是由于由正则表达式匹配的另外命名组,由指定的可选参数的外覆盖的 kwargs参数 django.conf.urls.url()。
  5. 如果没有正则表达式匹配,或者只要一个老大在是历程被的其他一样碰时提出,Django的调用适当的错误处理视图。

 

3、官方示例

1> 以下代码是官方示例:

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/([0-9]{4})/$', views.year_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

 笔记注意事项:

  • 假定捕获从URL中的价值,用括号括起来,会当参数传入 views 视图。
  • 从未必要添加一个斜线,因为每个URL都发生。例如,它^articles不是^/articles
  • 'r'前面的每个正则表达式字符串中凡是可选的,但建议。它报告Python字符串是“原始”
    -没有呀字符串中该进行转义。

 举例来说请求:

  • 请求 /articles/2005/03/以配合列表中的老三项。Django的将调用该函数 。views.month_archive(request,'2005', '03')
  • /articles/2005/3/  不会见配合任何 URL
    模式,因为以列表中的老三起中需简单各类数字之月。
  • /articles/2003/将匹配的列表,而休是次只第一美术,因为该图,以便测试,第一独凡是以首先测试通过。随意用顺序插入特殊情形是这样的。在此,Django的将调用该函数 views.special_case_2003(request)
  • /articles/2003 不配合任何这些模式,因为每个模式要求 URL
    以斜线结束。
  • /articles/2003/03/03/用匹配的末梢格局。Django
    的将调用该函数。views.article_detail(request,'2003', '03', '03')

 

 2> 命名组

地方的事例使用了简约的,非命名的正则表达式组(通过括号)来捕获 URL
的各类,并由此她们之职务参数的视图。在又高级的用法,它可行使命名 正则表达式组来捕获
URL 位,将其当做第一字参数传递给视图。

 在 Python
正则表达式,命名正则表达式组的语法(?P<name>pattern),这里 name凡是组的名称, pattern就算某种模式相配合。

 下面是点的事例中的URLconf,改写以命名组:

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]

随即恰恰就同样的作业,前面的例子,一个一线之出入:捕获的价值传递让查看功能作为重大字参数,而不是岗位参数。例如:

  • 请求/articles/2005/03/见面调用函数来替代,views.month_archive(request, year='2005',month='03')``views.month_archive(request, '2005', '03')
  • 请求/articles/2003/03/03/会调用该函数,views.article_detail(request, year='2003',month='03', day='03')

在实践中,这表示你的 URLconf 稍微重显,不爱参数顺序错误 –
你可以以你的意见’函数定义再度排序的参数。当然,这些亮点来在简约的花费; 一些开支任务命名组的语法丑陋,太长。

匹配/分组算法

此处的URL配置解析器遵循算法,相对于正则表达式命名组与非命名组:

  1. 一经产生其它命名参数,它见面用这些,而忽视非命名参数。
  2. 要不然,它见面经过拥有非命名参数作为职务参数。

以即时点儿种情景下,被给予以其他额外的严重性字参数传递额外的选取项来查阅功能为拿吃传送让视图

 

3> What the URLconf searches against

The URLconf searches against the requested URL, as a normal Python
string. This does not include GET or POST parameters, or the domain
name.

For example, in a request to https://www.example.com/myapp/, the
URLconf will look for myapp/.

In a request to https://www.example.com/myapp/?page=3, the URLconf
will look for myapp/.

欠URL配置不扣请求方法。换言之,所有的求的措施,GET,POST“ 等将让路由于到为同的URL,相同之效力。

 

4> 捕获的参数总是字符串

每个捕获的参数发送到视图作为普通的 Python
字符串,无论什么样的配合正则表达式匹配。

例如,在该URL配置行:

url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),

…的 year参数传递给 views.year_archive()将是一个字符串,

莫是一个平头,即使 [0-9]{4}用独自相当配整数字符串。

 

5> 指定view的默认设置

 一个好之技能是您的眼光的论证指定默认参数。下面是一个例证的 RLconf 和理念:

# URLconf
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^blog/$', views.page),
    url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]

# View (in blog/views.py)
def page(request, num="1"):
    # Output the appropriate page of blog entries, according to num.
    ...

每当上述的事例中,两只 URL
模式对同一个视图 views.page但首先贪图案不抓获从 URL
任何东西。如果第一只模式匹配,该 page()函数将使它们的默认参数 num"1"。如果第二图案相匹配时, page()拿采取任何 num价值由正则表达式捕获。

 

 6> 包括其他的URLconf 

当另时刻,你urlpatterns可“include”其他的URLconf模块。这精神上是“roots”的一致模仿低于其它的网址。

譬如,这里的URL配置也节选的Django网站 本身。它包括多外的URLconf的:

from django.conf.urls import include, url

urlpatterns = [
    # ... snip ...
    url(r'^community/', include('django_website.aggregator.urls')),
    url(r'^contact/', include('django_website.contact.urls')),
    # ... snip ...
]

央留意,在这事例中,正则表达式没有一个$ (结束字符串匹配字符),但包括从斜线。每当 Django 的遇到 include()django.conf.urls.include()),它卧关闭其他匹配到该点的URL的一律片,并拿余下的字符串所涵盖的URL配置用于更的处理。

其它一样种可能性是经行使的列表,以囊括另外的网址格式
 url()实例。例如,考虑这 URL 配置:

from django.conf.urls import include, url

from apps.main import views as main_views
from credit import views as credit_views

extra_patterns = [
    url(r'^reports/$', credit_views.report),
    url(r'^reports/(?P<id>[0-9]+)/$', credit_views.report),
    url(r'^charge/$', credit_views.charge),
]

urlpatterns = [
    url(r'^$', main_views.homepage),
    url(r'^help/', include('apps.help.urls')),
    url(r'^credit/', include(extra_patterns)),
]

在这个事例中,/credit/reports/URL将受处理 credit_views.report()的Django图。

自打里单个图案前缀被重复使用的URLconf去除冗余。

咱俩可通过声明的一路路径前缀只生雷同糟,分组,例如这URL配置:

from django.conf.urls import include, url
from . import views

urlpatterns = [
    url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/', include([
        url(r'^history/$', views.history),
        url(r'^edit/$', views.edit),
        url(r'^discuss/$', views.discuss),
        url(r'^permissions/$', views.permissions),
    ])),
]

 

7> 传递额外的挑项来查功能

URLconf
有一个牵连,可以传递额外的参数为你的视图功能,作为一个 Python
字典。

django.conf.urls.url()作用可采取这应当是格外的参数的字典传递给视图功能可摘的老三独参数。

例如:

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]

每当是例子中,用于向请求/blog/2005/,Django会调用 。views.year_archive(request, year='2005',foo='bar')

# 处理冲突

这可能有它可以捕获一个名为关键字参数的URL模式,并且还传递参数,在其额外的参数字典相同的名称。发生这种情况时,在字典中的参数将被用来代替在URL捕获的参数。

传送额外的选项来 include()

平等,您可以经额外的选项include()。当你通过额外的挑选include()每个着所蕴藏的URL配置线将经额外的选择项。

例如,这点儿只URL配置集在职能及是相同的:

# 设置一个:

# main.py
from django.conf.urls import include, url

urlpatterns = [
    url(r'^blog/', include('inner'), {'blogid': 3}),
]

# inner.py
from django.conf.urls import url
from mysite import views

urlpatterns = [
    url(r'^archive/$', views.archive),
    url(r'^about/$', views.about),
]

# 设置两个

# main.py
from django.conf.urls import include, url
from mysite import views

urlpatterns = [
    url(r'^blog/', include('inner')),
]

# inner.py
from django.conf.urls import url

urlpatterns = [
    url(r'^archive/$', views.archive, {'blogid': 3}),
    url(r'^about/$', views.about, {'blogid': 3}),
]

 

 

四、视图层

本着逻辑负责处理用户的要并回到响应。反回可以是HTML内容之网页,或再次定向,或404荒唐,或一个XML文件,或一个形象……此代码可以歇在另外你想去之地方,只要它在你的Python路径。

于一个文本被称将视图views.py,放在你的种类或者应用程序目录。

 1、返回快捷功能

render()

render(requesttemplate_namecontext=Nonecontent_type=Nonestatus=Noneusing=None)[source]

结给定的沙盘与一个加的上下文,返回一个字典HttpResponse在渲染文本对象

所用的参数

 template_name 一个模板的用或者模板序列名称全称。如果序列是加的,存在让第一独模板将吃运用。

可选参数

context    一组字典的值加加至模板被。默认情况下,这是一个拖欠的字典。

content_type    MIME类型用于转移文档。

status    为响应状态代码。默认值为200

using    这个名字一个模板引擎的行使以模板。

例子

from django.shortcuts import render

def my_view(request):
    # View code here...
    return render(request, 'myapp/index.html', {
        'foo': 'bar',
    }, content_type='application/xhtml+xml')

等价于

from django.http import HttpResponse
from django.template import loader

def my_view(request):
    # View code here...
    t = loader.get_template('myapp/index.html')
    c = {'foo': 'bar'}
    return HttpResponse(t.render(c, request), content_type='application/xhtml+xml')

 

 

render_to_response()

 render_to_response(template_namecontext=Nonecontent_type=Nonestatus=Noneusing=None)[source]

 这个与  render() 差不多,不推荐,在未来说不定丢掉掉

 

redirect()

 redirect(topermanent=False\args**kwargs*)[source]

 默认情况下,为即重定向;通过 permanent=True设置永久重定向

def my_view(request):
    ...
    return redirect('/some/url/')


def my_view(request):
    ...
    object = MyModel.objects.get(...)
    return redirect(object, permanent=True)

 

 2、求与应对象

Django 使用要和应对象在系统中传递状态。

当呼吁一个页面时,Django
创建一个 HttpRequest对象涵盖本数的乞求。然后 Django
加载适当的视图,通过 HttpRequest用作视图函数的首先单参数。每个视图负责返回一个HttpResponse目标。

HttpRequest对象

HttpRequest.scheme 

一个字符串表示请求的方案(HTTP或HTTPS)通常

HttpRequest.path

一个字符串的完整路径的请求

HttpRequest.method

请求的HTTP方法。这是保证要大写

if request.method == ‘GET’:
do_something()
elif request.method == ‘POST’:
do_something_else()

HttpRequest.GET

字典像包含所有给定的HTTP GET参数对象。

HttpRequest.POST

字典像包含所有给定的HTTP POST参数对象,提供请求包含表单数据。

HttpRequest.COOKIES

一个标准的Python字典,包含了所有的COOKIES,key和values都是字符串

HttpRequest.FILES

字典像对象包含所有上传的文件。
html 标签 <input type="file" name="" />

filename # 上传的文本名
content_type # 上污染文书之路
content # 上传文书的内容

HttpRequest.META

一个标准的Python字典包含所有可用的HTTP头。可用标题取决于客户端和服务器,但这里是一些例子:

CONTENT_LENGTH – 请求体的尺寸(一个字符串)。
CONTENT_TYPE – 请求体的品类。
HTTP_ACCEPT – 为响应–可以领的情类型。
HTTP_ACCEPT_ENCODING – 接受编码的应
HTTP_ACCEPT_LANGUAGE – 接受语言的反馈
HTTP_HOST – 客户端发送的HTTP主机头。
HTTP_REFERER – 参考页面
HTTP_USER_AGENT – 客户端的用户代理字符串。
QUERY_STRING – 查询字符串,作为一个单纯的(分析的)字符串。
REMOTE_ADDR – 客户端的IP地址
REMOTE_HOST – 客户端的主机名
REMOTE_USER – 用户通过Web服务器的身份验证。
REQUEST_METHOD – 字符串,如”GET”或”POST”
SERVER_NAME – 服务器的主机名
SERVER_PORT – 服务器的端口(一个字符串)。

 

HttpResponse对象

 对于HttpRequest 对象的话,是出于django自动创建的,但是,HttpResponse
对象就是不能不我们自己创建。每个 view 请求处理办法必须返回一个 HttpResponse
对象。

HttpResponse 类在 django.http.HttpResponse

 字符串使用:

卓越的用法是经过页面的情节,为一个字符串

>>> from django.http import HttpResponse
>>> response = HttpResponse("Here's the text of the Web page.")
>>> response = HttpResponse("Text only, please.", content_type="text/plain")

# 如果你想添加内容的增量
>>> response = HttpResponse()
>>> response.write("<p>Here's the text of the Web page.</p>")
>>> response.write("<p>Here's another paragraph.</p>")

特点和措施:

HttpResponse.content

一个bytestring代表内容

 HttpResponse.charset

一个字符串的字符集表示的响应将编码

HttpResponse.status_code

HTTP状态代码为响应码

HttpResponse.streaming

这个属性永远为假,一般用于中间件

HttpResponse.closed

关闭

 

方法:

HttpResponse.__init__(content=”, content_type=None, status=200,
reason=None, charset=None)[source]

实例化类自动执行的方法

HttpResponse.__setitem__(header, value)

为给定值给定的标题名称。都是字符串

HttpResponse.__delitem__(header)

删除标题的名称。不区分大小写。

HttpResponse.__getitem__(header)

获取给定标题名称。不区分大小写。

HttpResponse.has_header(header)

检查是否具有给定名称的一个标题

HttpResponse.setdefault(header, value)

设置一个标题,除非它已经设置。

HttpResponse.set_cookie(key, value=”, max_age=None, expires=None,
path=’/’, domain=None, secure=None, httponly=False)

设置一个cookie。参数跟标准库的Cookie对象差不多

HttpResponse.set_signed_cookie(key, value, salt=”, max_age=None,
expires=None, path=’/’, domain=None, secure=None, httponly=True)

加密cookice,可以用 HttpRequest.get_signed_cookie() 获取,当然你也可以加盐

HttpResponse.delete_cookie(key, path=’/’, domain=None)

删除Cookie与给定键。

 

HttpResponse子类:

class HttpResponseRedirect[source]

构造函数的第一个参数是必需的–路径redirectto。这是一个完全合格的URL(例如“https://www.yahoo.com /搜索/),没有一个绝对的路径(例如域搜索/ /),甚至是相对路径(如“/”)。在最后的情况下,客户端浏览器将重建完整的URL本身的电流路径。看到HttpResponse其他optionalconstructor参数。请注意,这将返回一个HTTP状态代码302。

class HttpResponsePermanentRedirect[source]

像httpresponseredirect,但它返回一个永久重定向(HTTP状态代码301)而不是“发现”的重定向(状态代码302)

class HttpResponseNotModified[source]

构造函数不带任何参数和NO含量应该被添加到这一反应。使用指定一个页面没有被modifiedsince用户的最后一个请求(状态代码304)。

class HttpResponseBadRequest[source]

就像HttpResponse但使用400状态码

class HttpResponseNotFound[source]

就像HttpResponse但使用404状态码

class HttpResponseForbidden[source]

就像HttpResponse但使用403状态码

class HttpResponseNotAllowed[source]

像HttpResponse,但使用405状态码。第一argumentto构造函数要求准许清单的方法(如(get,后])

class HttpResponseGone[source]

就像HttpResponse但使用410状态码

class HttpResponseServerError[source]

就像HttpResponse但使用500状态码

 

 

五、模板层

  作为一个Web框架,Django 需要模板。模板包含所欲的 HTML
输出静态部分与动态内容插入。

1、模版的执行

bifa365必发 5bifa365必发 6

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

from django import template
t = template.Template('My name is {{ name }}.')
c = template.Context({'name': 'Adrian'})
print t.render(c)

import datetime
from django import template
import DjangoDemo.settings

now = datetime.datetime.now()
fp = open(settings.BASE_DIR+'/templates/Home/Index.html')
t = template.Template(fp.read())
fp.close()
html = t.render(template.Context({'current_date': now}))
return HttpResponse(html

from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    t = get_template('current_datetime.html')
    html = t.render(Context({'current_date': now}))
    return HttpResponse(html)

return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))

示例

 

2、模版语言

 模板被吗产生友好之言语,该语言可以实现数据显示

  • {{ item }}
  • {% for item in item_list %}  <a>{{ item }}</a>  {%
    endfor %}
      forloop.counter
      forloop.first
      forloop.last 
  • {% if ordered_warranty %}  {% else %} {% endif %}
  • 母板:{% block title %}{% endblock %}
    子板:{% extends “base.html” %}
       {% block title %}{% endblock %}
  • 援方法:
    {{ item.event_start|date:”Y-m-d H:i:s”}}
    {{ bio|truncatewords:”30″ }}
    {{ my_list|first|upper }}
    {{ name|lower }}

 

3、自定义simple_tag

a、在app中创建templatetags模块

b、创建任意 .py 文件,如:xx.py

#!/usr/bin/env python
#coding:utf-8
from django import template
from django.utils.safestring import mark_safe
from django.template.base import resolve_variable, Node, TemplateSyntaxError

register = template.Library()

@register.simple_tag
def my_simple_time(v1,v2,v3):
    return  v1 + v2 + v3

@register.simple_tag
def my_input(id,arg):
    result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
    return mark_safe(result)

c、在动自定义simple_tag的html文件被导入之前创建的 xx.py 文件称

{% load xx %}

d、使用simple_tag

{% my_simple_time 1 2 3%}
{% my_input 'id_username' 'hide'%}

e、在settings中配备时app,不然django无法找到打定义的simple_tag

bifa365必发 7bifa365必发 8

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',
)

View Code

 

 

六、Model 层

Django提供了一个抽象层(“Model”)的构建和保管Web应用程序的数额。

  • 每个模型是一个Python类,子类d jango.db.models.model
  • 型中之每个属性代表一个数据库字段。

 

大概的例子

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

 

参数和字段

bifa365必发 9bifa365必发 10

1、models.AutoField  自增列 = int(11)
  如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
2、models.CharField  字符串字段
  必须 max_length 参数
3、models.BooleanField  布尔类型=tinyint(1)
  不能为空,Blank=True
4、models.ComaSeparatedIntegerField  用逗号分割的数字=varchar
  继承CharField,所以必须 max_lenght 参数
5、models.DateField  日期类型 date
  对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
6、models.DateTimeField  日期类型 datetime
  同DateField的参数
7、models.Decimal  十进制小数类型 = decimal
  必须指定整数位max_digits和小数位decimal_places
8、models.EmailField  字符串类型(正则表达式邮箱) =varchar
  对字符串进行正则表达式
9、models.FloatField  浮点类型 = double
10、models.IntegerField  整形
11、models.BigIntegerField  长整形
  integer_field_ranges = {
    'SmallIntegerField': (-32768, 32767),
    'IntegerField': (-2147483648, 2147483647),
    'BigIntegerField': (-9223372036854775808, 9223372036854775807),
    'PositiveSmallIntegerField': (0, 32767),
    'PositiveIntegerField': (0, 2147483647),
  }
12、models.IPAddressField  字符串类型(ip4正则表达式)
13、models.GenericIPAddressField  字符串类型(ip4和ip6是可选的)
  参数protocol可以是:both、ipv4、ipv6
  验证时,会根据设置报错
14、models.NullBooleanField  允许为空的布尔类型
15、models.PositiveIntegerFiel  正Integer
16、models.PositiveSmallIntegerField  正smallInteger
17、models.SlugField  减号、下划线、字母、数字
18、models.SmallIntegerField  数字
  数据库中的字段有:tinyint、smallint、int、bigint
19、models.TextField  字符串=longtext
20、models.TimeField  时间 HH:MM[:ss[.uuuuuu]]
21、models.URLField  字符串,地址正则表达式
22、models.BinaryField  二进制
23、models.ImageField   图片
24、models.FilePathField 文件

复多字段

bifa365必发 11bifa365必发 12

1、null=True
  数据库中字段是否可以为空
2、blank=True
  django的 Admin 中添加数据时是否可允许空值
3、primary_key = False
  主键,对AutoField设置主键后,就会代替原来的自增 id 列
4、auto_now 和 auto_now_add
  auto_now   自动创建---无论添加或修改,都是当前操作的时间
  auto_now_add  自动创建---永远是创建时的时间
5、choices
GENDER_CHOICE = (
        (u'M', u'Male'),
        (u'F', u'Female'),
    )
gender = models.CharField(max_length=2,choices = GENDER_CHOICE)
6、max_length
7、default  默认值
8、verbose_name  Admin中字段的显示名称
9、name|db_column  数据库中的字段名称
10、unique=True  不允许重复
11、db_index = True  数据库索引
12、editable=True  在Admin里是否可编辑
13、error_messages=None  错误提示
14、auto_created=False  自动创建
15、help_text  在Admin中提示帮助信息
16、validators=[]
17、upload-to

复多参数

 

连表结构

  • 一对多:models.ForeignKey(其他表)
  • 多对多:models.ManyToManyField(其他表)
  • 一对一:models.OneToOneField(其他表)

 

操作表

1、基本操作

# 增    
models.Tb1.objects.create(c1='xx', c2='oo')  # 增加一条数据,可以接受字典类型数据 **kwargs

obj = models.Tb1(c1='xx', c2='oo')
obj.save()

# 查    
models.Tb1.objects.get(id=123)          # 获取单条数据,不存在则报错(不建议)
models.Tb1.objects.all()                # 获取全部
models.Tb1.objects.filter(name='seven') # 获取指定条件的数据

# 删    
models.Tb1.objects.filter(name='nick').delete() # 删除指定条件的数据

# 改models.Tb1.objects.filter(name='nick').update(gender='0')  # 将指定条件的数据更新,均支持 **kwargs
obj = models.Tb1.objects.get(id=1)
obj.c1 = '111'
obj.save()                                                      # 修改单条数据

 

2、进阶操作(了不起的夹下划线)

采用双生划线将字段和相应的操作连接起来

# 获取个数
models.Tb1.objects.filter(name='nick').count()

# 大于,小于
models.Tb1.objects.filter(id__gt=1)              # 获取id大于1的值
models.Tb1.objects.filter(id__lt=10)             # 获取id小于10的值
models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值

# in
models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in

# contains
models.Tb1.objects.filter(name__contains="ven")
models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
models.Tb1.objects.exclude(name__icontains="ven")

# range
models.Tb1.objects.filter(id__range=[1, 2])      # 范围bettwen and

# 其他类似
# startswith,istartswith, endswith, iendswith,

# order by
models.Tb1.objects.filter(name='nick').order_by('id')    # asc
models.Tb1.objects.filter(name='nick').order_by('-id')   # desc

# limit 、offset
models.Tb1.objects.all()[10:20]

# group by
from django.db.models import Count, Min, Max, Sum

models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
# SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"

 

3、连表操作(了不起的双双下划线)

动用双生划线和 _set 将说明中的操作连接起来

bifa365必发 13bifa365必发 14

class UserProfile(models.Model):
    user_info = models.OneToOneField('UserInfo')
    username = models.CharField(max_length=64)
    password = models.CharField(max_length=64)

    def __unicode__(self):
        return self.username


class UserInfo(models.Model):
    user_type_choice = (
        (0, u'普通用户'),
        (1, u'高级用户'),
    )
    user_type = models.IntegerField(choices=user_type_choice)
    name = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
    address = models.CharField(max_length=128)

    def __unicode__(self):
        return self.name


class UserGroup(models.Model):

    caption = models.CharField(max_length=64)

    user_info = models.ManyToManyField('UserInfo')

    def __unicode__(self):
        return self.caption


class Host(models.Model):
    hostname = models.CharField(max_length=64)
    ip = models.GenericIPAddressField()
    user_group = models.ForeignKey('UserGroup')

    def __unicode__(self):
        return self.hostname

发明结构实例

bifa365必发 15bifa365必发 16

user_info_obj = models.UserInfo.objects.filter(id=1).first()
print user_info_obj.user_type
print user_info_obj.get_user_type_display()
print user_info_obj.userprofile.password

user_info_obj = models.UserInfo.objects.filter(id=1).values('email', 'userprofile__username').first()
print user_info_obj.keys()
print user_info_obj.values()

一定操作

bifa365必发 17bifa365必发 18

    # 添加一对多
    dic = {
        "hostname": "名字1",
        "ip": "192.168.1.1",
        "user_group_id": 1,   # 加对象则为"user_group"
    }
    models.Host.objects.create(**dic)

    # 正向查一对多
    host_obj = models.Host.objects.all()
    print(type(host_obj),     # <class 'django.db.models.query.QuerySet'>
          host_obj)           # <QuerySet [<Host: 名字1>]>
    for item in host_obj:
        print(item.hostname)
        print(item.user_group.caption)
        print(item.user_group.user_info.values())
        # <QuerySet [{'name': 'nick', 'user_type': 1, 'id': 1, 'email': '630571017@qq.com', 'address': '128号'}]>

    usergroup_obj = models.Host.objects.filter(user_group__caption='标题1')
    print(usergroup_obj)


    # 反向查一对多
    usergroup_obj = models.UserGroup.objects.get(id=1)
    print(usergroup_obj.caption)
    ret = usergroup_obj.host_set.all()  # 所有关于id=1的host
    print(ret)

    obj = models.UserGroup.objects.filter(host__ip='192.168.1.1').\
        values('host__id', 'host__hostname')
    print(obj)      # <QuerySet [{'host__id': 1, 'host__hostname': '名字1'}]>

一对多

bifa365必发 19bifa365必发 20

user_info_obj = models.UserInfo.objects.get(name='nick')
user_info_objs = models.UserInfo.objects.all()

group_obj = models.UserGroup.objects.get(caption='CTO')
group_objs = models.UserGroup.objects.all()

# 添加数据
#group_obj.user_info.add(user_info_obj)
#group_obj.user_info.add(*user_info_objs)

# 删除数据
#group_obj.user_info.remove(user_info_obj)
#group_obj.user_info.remove(*user_info_objs)

# 添加数据
#user_info_obj.usergroup_set.add(group_obj)
#user_info_obj.usergroup_set.add(*group_objs)

# 删除数据
#user_info_obj.usergroup_set.remove(group_obj)
#user_info_obj.usergroup_set.remove(*group_objs)

# 获取数据
#print group_obj.user_info.all()
#print group_obj.user_info.all().filter(id=1)

# 获取数据
#print user_info_obj.usergroup_set.all()
#print user_info_obj.usergroup_set.all().filter(caption='CTO')
#print user_info_obj.usergroup_set.all().filter(caption='DBA')

    # 添加多对多
    # userinfo_id_1 = models.UserInfo.objects.filter(id=1)
    # usergroup_id_1 = models.UserGroup.objects.filter(id=1).first()
    # usergroup_id_1.user_info.add(*userinfo_id_1)

大抵针对多操作

bifa365必发 21bifa365必发 22

    # F 使用查询条件的值(用原来的值操作)
    #
    # from django.db.models import F
    # models.Tb1.objects.update(num=F('num')+1)


    # Q 构建搜索条件
    from django.db.models import Q
    # con = Q()
    #
    # q1 = Q()
    # q1.connector = 'OR'
    # q1.children.append(('id', 1))
    # q1.children.append(('id', 10))
    # q1.children.append(('id', 9))
    #
    # q2 = Q()
    # q2.connector = 'OR'
    # q2.children.append(('c1', 1))
    # q2.children.append(('c1', 10))
    # q2.children.append(('c1', 9))
    #
    # con.add(q1, 'AND')
    # con.add(q2, 'AND')
    #
    # models.Tb1.objects.filter(con)

F & Q

bifa365必发 23bifa365必发 24

    from django.db import connection
    cursor = connection.cursor()
    cursor.execute("""SELECT * from app1_userinfo where name = %s""", ['nick'])
    row = cursor.fetchone()
    print(row)

Django 执行原生SQL

注意:xx_set中的【_set】是基本上对大多被的一贯搭配

 

扩展:

a、自定义及污染

bifa365必发 25bifa365必发 26

def upload_file(request):
    if request.method == "POST":
        obj = request.FILES.get('fafafa')
        f = open(obj.name, 'wb')
        for chunk in obj.chunks():
            f.write(chunk)
        f.close()
    return render(request, 'file.html')

View Code

b、Form上传文书实例

bifa365必发 27bifa365必发 28

       <form method="post" action="/view1/" enctype="multipart/form-data">
           <input type="file" name="ExcelFile" id="id_ExcelFile" />
           <input type="submit" value="提交" />
       </form>

HTML

bifa365必发 29bifa365必发 30

class FileForm(forms.Form):
    ExcelFile = forms.FileField()

Form

bifa365必发 31bifa365必发 32

from django.db import models

class UploadFile(models.Model):
    userid = models.CharField(max_length = 30)
    file = models.FileField(upload_to = './upload/')
    date = models.DateTimeField(auto_now_add=True)

models

bifa365必发 33bifa365必发 34

def UploadFile(request):
    uf = AssetForm.FileForm(request.POST,request.FILES)
    if uf.is_valid():
            upload = models.UploadFile()
            upload.userid = 1
            upload.file = uf.cleaned_data['ExcelFile']
            upload.save()

            print upload.file

View

c、ajax上污染文书实例

bifa365必发 35bifa365必发 36

   <div>
       {{ up.ExcelFile }}
       <input type="button" id="submitj" value="提交" />
   </div>


<script src="/static/js/jquery-2.1.4.min.js"></script>
<script>
    $('#submitj').bind("click",function () {
        var file = $('#id_ExcelFile')[0].files[0];
        var form = new FormData();
        form.append('ExcelFile', file);
         $.ajax({
                type:'POST',
                url: '/view1/',
                data: form,
                processData: false,  // tell jQuery not to process the data
                contentType: false,  // tell jQuery not to set contentType
                success: function(arg){
                    console.log(arg);
                }
            })
    })
</script>

HTML

bifa365必发 37bifa365必发 38

class FileForm(forms.Form):
    ExcelFile = forms.FileField()

Form

bifa365必发 39bifa365必发 40

from django.db import models

class UploadFile(models.Model):
    userid = models.CharField(max_length = 30)
    file = models.FileField(upload_to = './upload/')
    date = models.DateTimeField(auto_now_add=True)

models

bifa365必发 41bifa365必发 42

from study1 import forms

def UploadFile(request):
    uf = AssetForm.FileForm(request.POST,request.FILES)
    if uf.is_valid():
            upload = models.UploadFile()
            upload.userid = 1
            upload.file = uf.cleaned_data['ExcelFile']
            upload.save()

            print upload.file

return render(request, 'file.html', locals())

View

 

 

七、Form

django中的Form一般有个别栽意义:

  • 输入html
  • 证明用户输入

bifa365必发 43bifa365必发 44

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
from django import forms
from django.core.exceptions import ValidationError


def mobile_validate(value):
    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
    if not mobile_re.match(value):
        raise ValidationError('手机号码格式错误')


class PublishForm(forms.Form):

    user_type_choice = (
        (0, u'普通用户'),
        (1, u'高级用户'),
    )

    user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
                                                                  attrs={'class': "form-control"}))

    title = forms.CharField(max_length=20,
                            min_length=5,
                            error_messages={'required': u'标题不能为空',
                                            'min_length': u'标题最少为5个字符',
                                            'max_length': u'标题最多为20个字符'},
                            widget=forms.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'标题5-20个字符'}))

    memo = forms.CharField(required=False,
                           max_length=256,
                           widget=forms.widgets.Textarea(attrs={'class': "form-control no-radius", 'placeholder': u'详细描述', 'rows': 3}))

    phone = forms.CharField(validators=[mobile_validate, ],
                            error_messages={'required': u'手机不能为空'},
                            widget=forms.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'手机号码'}))

    email = forms.EmailField(required=False,
                            error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'},
                            widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))

Form

bifa365必发 45bifa365必发 46

def publish(request):
    ret = {'status': False, 'data': '', 'error': '', 'summary': ''}
    if request.method == 'POST':
        request_form = PublishForm(request.POST)
        if request_form.is_valid():
            request_dict = request_form.clean()
            print request_dict
            ret['status'] = True
        else:
            error_msg = request_form.errors.as_json()
            ret['error'] = json.loads(error_msg)
    return HttpResponse(json.dumps(ret))

View Code

扩展:ModelForm

于行使Model和Form时,都待针对字段进行定义并指定项目,通过ModelForm则可以看去From中字段的概念

bifa365必发 47bifa365必发 48

class AdminModelForm(forms.ModelForm):

    class Meta:
        model = models.Admin
        #fields = '__all__'
        fields = ('username', 'email')

        widgets = {
            'email' : forms.PasswordInput(attrs={'class':"alex"}),
        }

View Code

 

 

八、认证系统auth 

auth模块是Django提供的业内权限管理体系,可以提供用户位置认证,
用户组管理,并且可与admin模块配合使用.

在INSTALLED_APPS中补充加’django.contrib.auth’使用该APP, auth模块默认启用.

model

from django.contrib.auth.models import User

# 数据库中该表名为auth_user.
CREATE TABLE "auth_user" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "password" varchar(128) NOT NULL, "last_login" datetime NULL, 
    "is_superuser" bool NOT NULL, 
    "first_name" varchar(30) NOT NULL, 
    "last_name" varchar(30) NOT NULL,
    "email" varchar(254) NOT NULL, 
    "is_staff" bool NOT NULL, 
    "is_active" bool NOT NULL,
    "date_joined" datetime NOT NULL,
    "username" varchar(30) NOT NULL UNIQUE
)

新建用户

user = User.objects.create_user(username, email, password)
user.save()

# 不存储用户密码明文而是存储一个Hash值

征用户

from django.contrib.auth import authenticate

user = authenticate(username=username, password=password)

# 认证用户的密码是否有效, 若有效则返回代表该用户的user对象, 若无效则返回None.
# 该方法不检查is_active标志位.

修改密码

user.set_password(new_password)

# 以下实例为先认证通过后才可以修改密码
user = auth.authenticate(username=username, password=old_password)
if user is not None:
    user.set_password(new_password)
    user.save()

登录

from django.contrib.auth import login

# login向session中添加SESSION_KEY, 便于对用户进行跟踪:
'login(request, user)'

# login不进行认证,也不检查is_active标志位
# 实例
user = authenticate(username=username, password=password)
if user is not None:
    if user.is_active:
        login(request, user)

退登录

# logout会移除request中的user信息, 并刷新session

from django.contrib.auth import logout

def logout_view(request):
    logout(request)

光同意登录的用户访问

@login_required修饰器修饰的view函数会事先通过session key检查是否登录,
已登录用户可正常的实行操作,
未登录用户以于重定向到login_url点名的bifa365必发位置.

比方无指定login_url参数, 则重定向到settings.LOGIN_URL

from django.contrib.auth.decorators import login_required

@login_required(login_url='/accounts/login/')
def userinfo(request):
    ...

# settings 配置
LOGIN_URL = '/index/'
# views
@login_required
def userinfo(request):
    ...

 

九、跨站请求伪造

简介

django为用户实现防止跨站请求伪造之效力,通过中间件 django.middleware.csrf.CsrfViewMiddleware
来好。而对于django中设置防跨站请求伪造功能有分为全局与有些。

全局:

  中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

  • @csrf_protect,为眼前函数强制安装防跨站请求伪造功能,即便settings中无装全局中件。
  • @csrf_exempt,取消时函数防跨站请求伪造功能,即便settings中安了大局中件。

注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

 

应用

1、普通表单

veiw中设置返回值:
  return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))  
     或者
     return render(request, 'xxx.html', data)

html中设置Token:
  {% csrf_token %}

2、Ajax

于传统的form,可以透过表单的道以token再次发送至服务端,而对于ajax的讲话,使用如下方式。

bifa365必发 49bifa365必发 50

# view.py

from django.template.context import RequestContext
# Create your views here.


def test(request):

    if request.method == 'POST':
        print request.POST
        return HttpResponse('ok')
    return  render_to_response('app01/test.html',context_instance=RequestContext(request))

view.py

bifa365必发 51bifa365必发 52

# text.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    {% csrf_token %}

    <input type="button" onclick="Do();"  value="Do it"/>

    <script src="/static/plugin/jquery/jquery-1.8.0.js"></script>
    <script src="/static/plugin/jquery/jquery.cookie.js"></script>
    <script type="text/javascript">
        var csrftoken = $.cookie('csrftoken');

        function csrfSafeMethod(method) {
            // these HTTP methods do not require CSRF protection
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
        }
        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            }
        });
        function Do(){

            $.ajax({
                url:"/app01/test/",
                data:{id:1},
                type:'POST',
                success:function(data){
                    console.log(data);
                }
            });

        }
    </script>
</body>
</html>

text.html

更多:https://docs.djangoproject.com/en/dev/ref/csrf/\#ajax

 

 

十、分页

Django内置分页 

Paginator

 

从今定义分页

bifa365必发 53bifa365必发 54

#!/usr/bin/env python
# _*_coding:utf-8_*_
from django.utils.safestring import mark_safe

class PageInfo(object):
    def __init__(self,current,totalItem,peritems=5):
        self.__current=current
        self.__peritems=peritems
        self.__totalItem=totalItem
    def From(self):
        return (self.__current-1)*self.__peritems
    def To(self):
        return self.__current*self.__peritems
    def TotalPage(self):  #总页数
        result=divmod(self.__totalItem,self.__peritems)
        if result[1]==0:
            return result[0]
        else:
            return result[0]+1

def Custompager(baseurl,currentPage,totalpage):  #基础页,当前页,总页数
    perPager=11
    #总页数<11
    #0 -- totalpage
    #总页数>11
        #当前页大于5 currentPage-5 -- currentPage+5
            #currentPage+5是否超过总页数,超过总页数,end就是总页数
        #当前页小于5 0 -- 11
    begin=0
    end=0
    if totalpage <= 11:
        begin=0
        end=totalpage
    else:
        if currentPage>5:
            begin=currentPage-5
            end=currentPage+5
            if end > totalpage:
                end=totalpage
        else:
            begin=0
            end=11
    pager_list=[]
    if currentPage<=1:
        first="<a href=''>首页</a>"
    else:
        first="<a href='%s%d'>首页</a>" % (baseurl,1)
    pager_list.append(first)

    if currentPage<=1:
        prev="<a href=''>上一页</a>"
    else:
        prev="<a href='%s%d'>上一页</a>" % (baseurl,currentPage-1)
    pager_list.append(prev)

    for i in range(begin+1,end+1):
        if i == currentPage:
            temp="<a href='%s%d' class='selected'>%d</a>" % (baseurl,i,i)
        else:
            temp="<a href='%s%d'>%d</a>" % (baseurl,i,i)
        pager_list.append(temp)
    if currentPage>=totalpage:
        next="<a href='#'>下一页</a>"
    else:
        next="<a href='%s%d'>下一页</a>" % (baseurl,currentPage+1)
    pager_list.append(next)
    if currentPage>=totalpage:
        last="<a href=''>末页</a>"
    else:
        last="<a href='%s%d'>末页</a>" % (baseurl,totalpage)
    pager_list.append(last)
    result=''.join(pager_list)
    return mark_safe(result)   #把字符串转成html语言

分页实例

 

 

十一、Cookice

获取Cookie:

request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
    参数:
        default: 默认值
           salt: 加密盐
        max_age: 后台控制过期时间

 

设置Cookie:

rep = HttpResponse(...) 或 rep = render(request, ...)

rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密盐',...)
    参数:
        key,              键
        value='',         值
        max_age=None,     超时时间
        expires=None,     超时时间(IE requires expires, so set it if hasn't been already.)
        path='/',         Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问
        domain=None,      Cookie生效的域名
        secure=False,     https传输
        httponly=False    只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

出于cookie保存在客户端的微处理器及,所以,JavaScript和jquery也足以操作cookie。

<script src='/static/js/jquery.cookie.js'></script>
$.cookie("list_pager_num", 30,{ path: '/' });

 

 

十二、Session

Django中默认支持Session,其里面提供了5种类型的Session供开发者使用:

  • 数据库(默认)
  • 缓存
  • 文件
  • 缓存+数据库
  • 加密cookie

1、数据库Session

bifa365必发 55bifa365必发 56

Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。

a. 配置 settings.py

    SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)

    SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
    SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
    SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
    SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
    SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)
    SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
    SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)



b. 使用

    def index(request):
        # 获取、设置、删除Session中数据
        request.session['k1']
        request.session.get('k1',None)
        request.session['k1'] = 123
        request.session.setdefault('k1',123) # 存在则不设置
        del request.session['k1']

        # 所有 键、值、键值对
        request.session.keys()
        request.session.values()
        request.session.items()
        request.session.iterkeys()
        request.session.itervalues()
        request.session.iteritems()


        # 用户session的随机字符串
        request.session.session_key

        # 将所有Session失效日期小于当前日期的数据删除
        request.session.clear_expired()

        # 检查 用户session的随机字符串 在数据库中是否
        request.session.exists("session_key")

        # 删除当前用户的所有Session数据
        request.session.delete("session_key")

        ...

View Code

2、缓存Session

bifa365必发 57bifa365必发 58

a. 配置 settings.py

    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
    SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置


    SESSION_COOKIE_NAME = "sessionid"                        # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
    SESSION_COOKIE_PATH = "/"                                # Session的cookie保存的路径
    SESSION_COOKIE_DOMAIN = None                              # Session的cookie保存的域名
    SESSION_COOKIE_SECURE = False                             # 是否Https传输cookie
    SESSION_COOKIE_HTTPONLY = True                            # 是否Session的cookie只支持http传输
    SESSION_COOKIE_AGE = 1209600                              # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # 是否关闭浏览器使得Session过期
    SESSION_SAVE_EVERY_REQUEST = False                        # 是否每次请求都保存Session,默认修改之后才保存



b. 使用

    同上

View Code

3、文件Session

bifa365必发 59bifa365必发 60

a. 配置 settings.py

    SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
    SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T


    SESSION_COOKIE_NAME = "sessionid"                          # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
    SESSION_COOKIE_PATH = "/"                                  # Session的cookie保存的路径
    SESSION_COOKIE_DOMAIN = None                                # Session的cookie保存的域名
    SESSION_COOKIE_SECURE = False                               # 是否Https传输cookie
    SESSION_COOKIE_HTTPONLY = True                              # 是否Session的cookie只支持http传输
    SESSION_COOKIE_AGE = 1209600                                # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                     # 是否关闭浏览器使得Session过期
    SESSION_SAVE_EVERY_REQUEST = False                          # 是否每次请求都保存Session,默认修改之后才保存

b. 使用

    同上

View Code

4、缓存+数据库Session

bifa365必发 61bifa365必发 62

数据库用于做持久化,缓存用于提高效率

a. 配置 settings.py

    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎

b. 使用

    同上

View Code

5、加密cookie Session

bifa365必发 63bifa365必发 64

a. 配置 settings.py

    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎

b. 使用

    同上

View Code

再也多参考:撞倒这里 和 碰上这里

扩张:Session用户征

def login(func):
    def wrap(request, *args, **kwargs):
        # 如果未登陆,跳转到指定页面
        if request.path == '/test/':
            return redirect('http://www.baidu.com')
        return func(request, *args, **kwargs)
    return wrap

 

6、Redis 实现 

环境设置

pip install django-redis
pip install django-redis-cache
pip install django-redis-sessions
1> 配置django-redis-sessions

在settings.py中配置

SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
# SESSION_ENGINE = 'redis_sessions.session'
SESSION_REDIS_HOST = 'localhost'
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 0
SESSION_REDIS_PASSWORD = 'password'
SESSION_REDIS_PREFIX = 'session'
SESSION_COOKIE_NAME = 'session_name'
SESSION_COOKIE_AGE = '60*20'  # 超时时间


# If you prefer domain socket connection, you can just add this line instead of SESSION_REDIS_HOST and SESSION_REDIS_PORT.
SESSION_REDIS_UNIX_DOMAIN_SOCKET_PATH = '/var/run/redis/redis.sock'

安排好后只是测试如下:

$ pip install django nose redis
# Make sure you have redis running on localhost:6379
(poem)[beginman@beginman poem]$ nosetests

----------------------------------------------------------------------
Ran 0 tests in 0.001s

OK
2> 配置django-redis-sessions

在settings.py中配置

CACHES = {
        "default": {
            "BACKEND": "django_redis.cache.RedisCache",
            "LOCATION": [
                "redis://:password@IP0.0.0.0:6379",
            ],
            "OPTIONS": {
                # "CLIENT_CLASS": "django_redis.client.DefaultClient",
                "CONNECTION_POOL_KWARGS": {"max_connections": 100},     # 连接池
            }
        }
    }

bifa365必发 65bifa365必发 66

CACHES = {
    'default': {
        'BACKEND': 'redis_cache.RedisCache',
        'LOCATION': '<host>:<port>',
        'OPTIONS': {
            'DB': 1,
            'PASSWORD': '',
            'PARSER_CLASS': 'redis.connection.HiredisParser',
            'CONNECTION_POOL_CLASS': 'redis.BlockingConnectionPool',
            'CONNECTION_POOL_CLASS_KWARGS': {
                'max_connections': 50,
                'timeout': 20,
            }
        },
    },
}

View Code

3>django实现redis的存取
# Start by importing your default cache:
from django.core.cache import cache

# Store data under a-unique-key:
cache.set('a-unique-key', 'this is a string which will be cached')

# Later on you can retrieve it in another function:
cache.get('a-unique-key') # Will return None if key is not found in cache

# You can specify a default value:
cache.get('another-unique-key', 'default value')

# You can store multiple values at once:
cache.set_many({'a': 1, 'b': 2, 'c': 3})

# And fetch multiple values:
cache.get_many(['a', 'b', 'c']) # returns {'a': 1, 'b': 2, 'c': 3}

# You can store complex types in the cache:
cache.set('a-unique-key', {
    'string'    : 'this is a string',
    'int'       : 42,
    'list'      : [1, 2, 3],
    'tuple'     : (1, 2, 3),
    'dict'      : {'A': 1, 'B' : 2},
})

更多:http://niwinz.github.io/django-redis/latest/\#\_installation 

 

十三、缓存

鉴于Django是动态网站,所有每次要都会失掉数进行相应的操作,当次访问量大时,耗时必会更加扎眼,最简易解决办法是采取:缓存,缓存将一个有views的返回值保存及内存还是memcache中,5分钟内重新有人来做客时,则不再去执行view中之操作,而是直接从内存还是Redis中前缓存的始末将到,并赶回。

Django中提供了6种植缓存方式:

  • 出调试
  • 内存
  • 文件
  • 数据库
  • Memcache缓存(python-memcached模块)
  • Memcache缓存(pylibmc模块)

1、配置

a、开发调试

bifa365必发 67bifa365必发 68

# 此为开始调试用,实际内部不做任何操作
    # 配置:
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.dummy.DummyCache',     # 引擎
                'TIMEOUT': 300,                                               # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
                'OPTIONS':{
                    'MAX_ENTRIES': 300,                                       # 最大缓存个数(默认300)
                    'CULL_FREQUENCY': 3,                                      # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
                },
                'KEY_PREFIX': '',                                             # 缓存key的前缀(默认空)
                'VERSION': 1,                                                 # 缓存key的版本(默认1)
                'KEY_FUNCTION' 函数名                                          # 生成key的函数(默认函数会生成为:【前缀:版本:key】)
            }
        }


    # 自定义key
    def default_key_func(key, key_prefix, version):
        """
        Default function to generate keys.

        Constructs the key used by all other methods. By default it prepends
        the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
        function with custom key making behavior.
        """
        return '%s:%s:%s' % (key_prefix, version, key)

    def get_key_func(key_func):
        """
        Function to decide which key function to use.

        Defaults to ``default_key_func``.
        """
        if key_func is not None:
            if callable(key_func):
                return key_func
            else:
                return import_string(key_func)
        return default_key_func

View Code

b、内存

bifa365必发 69bifa365必发 70

# 此缓存将内容保存至内存的变量中
    # 配置:
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
                'LOCATION': 'unique-snowflake',
            }
        }

    # 注:其他配置同开发调试版本

View Code

c、文件

bifa365必发 71bifa365必发 72

# 此缓存将内容保存至文件
    # 配置:

        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
                'LOCATION': '/var/tmp/django_cache',
            }
        }
    # 注:其他配置同开发调试版本

View Code

d、数据库

bifa365必发 73bifa365必发 74

# 此缓存将内容保存至数据库

    # 配置:
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
                'LOCATION': 'my_cache_table', # 数据库表
            }
        }

    # 注:执行创建表命令 python manage.py createcachetable

View Code

e、Memcache缓存(python-memcached模块)

bifa365必发 75bifa365必发 76

# 此缓存使用python-memcached模块连接memcache

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': '127.0.0.1:11211',
        }
    }

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': 'unix:/tmp/memcached.sock',
        }
    }   

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': [
                '172.19.26.240:11211',
                '172.19.26.242:11211',
            ]
        }
    }

View Code

f、Memcache缓存(pylibmc模块)

bifa365必发 77bifa365必发 78

# 此缓存使用pylibmc模块连接memcache

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
            'LOCATION': '127.0.0.1:11211',
        }
    }

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
            'LOCATION': '/tmp/memcached.sock',
        }
    }   

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
            'LOCATION': [
                '172.19.26.240:11211',
                '172.19.26.242:11211',
            ]
        }
    }

View Code

 

2、应用

a、 全站使用

bifa365必发 79bifa365必发 80

使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存

    MIDDLEWARE = [
        'django.middleware.cache.UpdateCacheMiddleware',
        # 其他中间件...
        'django.middleware.cache.FetchFromCacheMiddleware',
    ]

    CACHE_MIDDLEWARE_ALIAS = ""
    CACHE_MIDDLEWARE_SECONDS = ""
    CACHE_MIDDLEWARE_KEY_PREFIX = ""

View Code

b、单独看图缓存

bifa365必发 81bifa365必发 82

方式一:
        from django.views.decorators.cache import cache_page

        @cache_page(60 * 15)
        def my_view(request):
            ...

    方式二:
        from django.views.decorators.cache import cache_page

        urlpatterns = [
            url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)),
        ]

View Code

c、局部视图使用

bifa365必发 83bifa365必发 84

a. 引入TemplateTag

        {% load cache %}

    b. 使用缓存

        {% cache 5000 缓存key %}
            缓存内容
        {% endcache %}

View Code

更多:打这里

 

 

十四、序列化

关于Django中的序列化主要使用在以数据库被搜索的数返回给客户端用户,特别的Ajax请求一般返回的也罢Json格式。

1、serializers

from django.core import serializers

ret = models.BookType.objects.all()

data = serializers.serialize("json", ret)

2、json.dumps

import json

#ret = models.BookType.objects.all().values('caption')
ret = models.BookType.objects.all().values_list('caption')

ret=list(ret)

result = json.dumps(ret)

由于json.dumps时无法处理datetime日期,所以可以经过由定义处理器来开扩展,如:

bifa365必发 85bifa365必发 86

import json 
from datetime import date 
from datetime import datetime 

class JsonCustomEncoder(json.JSONEncoder): 

    def default(self, field): 

        if isinstance(field, datetime): 
            return o.strftime('%Y-%m-%d %H:%M:%S') 
        elif isinstance(field, date): 
            return o.strftime('%Y-%m-%d') 
        else: 
            return json.JSONEncoder.default(self, field) 


# ds = json.dumps(d, cls=JsonCustomEncoder) 

View Code

 

 

十五、中间件

django
中之中间件(middleware),在django中,中间件实在就算是一个类,在求到来和收晚,django会根据自己之规则以方便的空子执行中件中相应的法子。

在django项目的settings模块中,有一个
MIDDLEWARE_CLASSES 变量,其中各级一个要素就是是一个当中件,如下图。

bifa365必发 87

同mange.py在同等目录下的文件夹
wupeiqi/middleware下的auth.py文件中之Authentication类

高中级件被好定义四个方式,分别是:

  • process_request(self,request)
  • process_view(self, request, callback, callback_args,
    callback_kwargs)
  • process_template_response(self,request,response)
  • process_exception(self, request, exception)
  • process_response(self, request, response)

以上办法的返回值可以是None和HttpResonse对象,如果是None,则连续按照django定义的条条框框为下实行,如果是HttpResonse对象,则一直拿该对象回来给用户。

bifa365必发 88

由定义中间件

1、创建中件类

class RequestExeute(object):

    def process_request(self,request):
        pass
    def process_view(self, request, callback, callback_args, callback_kwargs):
        i =1
        pass
    def process_exception(self, request, exception):
        pass

    def process_response(self, request, response):
        return response

2、注册中件

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'wupeiqi.middleware.auth.RequestExeute',
)

 

 

十六、信号

Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是片动作来的当儿,信号允许特定的发送者去提醒有接受者。

1、Django内置信号

Model signals
    pre_init                    # django的modal执行其构造方法前,自动触发
    post_init                   # django的modal执行其构造方法后,自动触发
    pre_save                    # django的modal对象保存前,自动触发
    post_save                   # django的modal对象保存后,自动触发
    pre_delete                  # django的modal对象删除前,自动触发
    post_delete                 # django的modal对象删除后,自动触发
    m2m_changed                 # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
    class_prepared              # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
Management signals
    pre_migrate                 # 执行migrate命令前,自动触发
    post_migrate                # 执行migrate命令后,自动触发
Request/response signals
    request_started             # 请求到来前,自动触发
    request_finished            # 请求结束后,自动触发
    got_request_exception       # 请求异常后,自动触发
Test signals
    setting_changed             # 使用test测试修改配置文件时,自动触发
    template_rendered           # 使用test测试渲染模板时,自动触发
Database Wrappers
    connection_created          # 创建数据库连接时,自动触发

对Django内置的信号,仅需报指定信号,当程序执行相应操作时,自动触发注册函数:

bifa365必发 89bifa365必发 90

from django.core.signals import request_finished
    from django.core.signals import request_started
    from django.core.signals import got_request_exception

    from django.db.models.signals import class_prepared
    from django.db.models.signals import pre_init, post_init
    from django.db.models.signals import pre_save, post_save
    from django.db.models.signals import pre_delete, post_delete
    from django.db.models.signals import m2m_changed
    from django.db.models.signals import pre_migrate, post_migrate

    from django.test.signals import setting_changed
    from django.test.signals import template_rendered

    from django.db.backends.signals import connection_created


    def callback(sender, **kwargs):
        print("xxoo_callback")
        print(sender,kwargs)

    xxoo.connect(callback)
    # xxoo指上述导入的内容

View Code

bifa365必发 91bifa365必发 92

from django.core.signals import request_finished
from django.dispatch import receiver

@receiver(request_finished)
def my_callback(sender, **kwargs):
    print("Request finished!")

View Code

2、自定义信号

a. 定义信号

import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

b. 注册信号

def callback(sender, **kwargs):
    print("callback")
    print(sender,kwargs)

pizza_done.connect(callback)

c. 触发信号

from 路径 import pizza_done

pizza_done.send(sender='seven',toppings=123, size=456)

由放信号的触发者已经合并到Django中,所以其会面活动调用,而对自定义信号则需开发者在任意位置点。

更多:相撞这里

 

 

十七、admin

django
amdin是django提供的一个后台管理页面,改管理页面提供到之html和css,使得你以经Model创建了数据库表之后,就得对数据开展增删改查,而采用django
admin 则要以下步骤:

  • 创办后台管理员
  • 配置url
  • 登记与配备django admin后台管理页面

1、创建后台管理员

python manage.py createsuperuser

2、配置后台管理url

url(r'^admin/', include(admin.site.urls))

3、注册与布局django admin 后台管理页面

a、在admin中实行如下配置

bifa365必发 93bifa365必发 94

from django.contrib import admin

from app01 import  models

admin.site.register(models.UserType)
admin.site.register(models.UserInfo)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)

View Code

b、设置数据表名称

bifa365必发 95bifa365必发 96

class UserType(models.Model):
    name = models.CharField(max_length=50)

    class Meta:
        verbose_name = '用户类型'
        verbose_name_plural = '用户类型'

View Code

c、打开表之后,设定默认显示,需要以model中犯如下配置

bifa365必发 97bifa365必发 98

class UserType(models.Model):
    name = models.CharField(max_length=50)

    def __unicode__(self):
        return self.name

View Code

bifa365必发 99bifa365必发 100

from django.contrib import admin

from app01 import  models

class UserInfoAdmin(admin.ModelAdmin):
    list_display = ('username', 'password', 'email')


admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)

View Code

d、为数表添加搜索效果

bifa365必发 101bifa365必发 102

from django.contrib import admin

from app01 import  models

class UserInfoAdmin(admin.ModelAdmin):
    list_display = ('username', 'password', 'email')
    search_fields = ('username', 'email')

admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)

View Code

e、添加疾过滤

bifa365必发 103bifa365必发 104

from django.contrib import admin

from app01 import  models

class UserInfoAdmin(admin.ModelAdmin):
    list_display = ('username', 'password', 'email')
    search_fields = ('username', 'email')
    list_filter = ('username', 'email')



admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)

View Code

更多:http://docs.30c.org/djangobook2/chapter06/

 

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注