一杯咖啡时间学会 Django

Posted suoning

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一杯咖啡时间学会 Django相关的知识,希望对你有一定的参考价值。

一、Django 简介

  Django 是一个由 Python 写成的开放源代码的 Web 应用框架。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是 CMS(内容管理系统)软件。并于2005年7月在 BSD 许可证下发布。这套框架是以比利时的吉普赛爵士吉他手 Django Reinhardt 来命名的。由于 Django 的是在一个快节奏的新闻编辑室环境下开发的,它的目的是使常见的 Web 开发任务,快速和容易。

 

MTV 模式

Django 采用了 MTV 设计模式

上述图大概是说:

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

 

 

 安装

# 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函数得多接受一个参数 
# 对应接收值

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、模版的执行

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、模版语言

 模板中也有自己的语言,该语言可以实现数据展示