精华内容
参与话题
问答
  • Django框架介绍及配置

    千次阅读 2019-02-24 18:53:46
    Django框架介绍及配置 一, WEB框架介绍 1.1Web应用程序处理流程 1.2Web框架程序的意义 用于搭建Web应用程序 免去不同Web应用相同代码部分的重复 1.3 Web应用程序的本质 接收并解析HTTP请求,获取具体的请求信息 ...

    Django框架介绍及配置

    一, WEB框架介绍

    1.1Web应用程序处理流程

    在这里插入图片描述

    1.2Web框架程序的意义

    用于搭建Web应用程序
    免去不同Web应用相同代码部分的重复

    1.3 Web应用程序的本质

    接收并解析HTTP请求,获取具体的请求信息
    处理本次HTTP请求,即完成本次请求的业务逻辑处理
    构造并返回处理结果——HTTP响应

    1.4. Web框架学习方法

    这三天我们的学习目标和最终任务:

    如何搭建工程程序

    工程的组建
    工程的配置
    路由定义
    视图函数定义

    如何获取请求数据(操作request对象)

    如何构造响应数据(构造response对象)

    如何使用中间层

    框架提供的其他功能组件的使用

    数据库
    模板
    表单
    admin

    二,Django框架介绍

    2.1 简介

    Django,发音为[`dʒæŋɡəʊ],

    django是用python语言写的开源web开发框架,并遵循MVC设计。

    诞生历史: 劳伦斯出版集团为了开发以新闻内容为主的网站,而开发出来了这个框架,于2005年7月在BSD许可证下发布。这个名称来源于比利时的爵士音乐家DjangoReinhardt,他是一个吉普赛人,主要以演奏吉它为主,还演奏过小提琴等。

    由于Django在近年来的迅速发展,应用越来越广泛,被著名IT开发杂志SDTimes评选为2013SDTimes100,位列"API、库和框架"分类第6位,被认为是该领域的佼佼者。

    django_belief

    2.2 特点

    1) 重量级框架

    对比Flask框架,Django原生提供了众多的功能组件,让开发更简便快速。
    1)提供项目工程管理的自动化脚本工具( 脚手架工具 )
    2)数据库ORM支持(对象关系映射,英语:Object Relational Mapping)
    3)模板
    4)表单
    5)Admin管理站点
    6)文件管理
    7)认证权限
    8)session机制
    9)缓存

    2)MVT模式

    有一种程序设计模式叫MVC, 其核心思想是分工、解耦,让不同的代码块之间降低耦合,增强代码的可扩展性和可移植性,实现向后兼容。

    MVC的全拼为Model-View-Controller,最早由TrygveReenskaug在1978年提出,是施乐帕罗奥多研究中心(Xerox PARC)在20世纪80年代为程序语言Smalltalk发明的一种软件设计模式,是为了将传统的输入(input)、处理(processing)、输出(output)任务运用到图形化用户交互模型中而设计的。

    随着标准输入输出设备的出现,开发人员只需要将精力集中在业务逻辑的分析与实现上。

    后来被推荐为Oracle旗下Sun公司Java EE平台的设计模式,并且受到越来越多的使用ColdFusion和PHP的开发者的欢迎。

    现在虽然不再使用原来的分工方式,但是这种分工的思想被沿用下来,广泛应用于软件工程中,是一种典型并且应用广泛的软件架构模式。

    后来,MVC的思想被应用在了Web开发方面,被称为Web MVC框架。

    3)MVC模式说明

    mvc

    M全拼为Model,主要封装对数据库层的访问,对数据库中的数据进行增、删、改、查操作。
    V全拼为View,用于封装结果,生成页面展示的html内容。
    C全拼为Controller,用于接收请求,处理业务逻辑,与Model和View交互,返回结果。

    4)Django使用的MVT模式说明

    mvt

    M全拼为Model,与MVC中的M功能相同,负责和数据库交互,进行数据处理。
    V全拼为View,与MVC中的C功能相同,接收请求,进行业务处理,返回应答。
    T全拼为Template,与MVC中的V功能相同,负责封装构造要返回的html。

    注:

    差异就在于黑线黑箭头标识出来的部分
    具体差异不是很多,叫法和代码不同, 思路相同.

    5). Django学习资料

    官方网站
    Github源码
    1.11版英文文档
    1.11版中文文档
    Django Book 教程
    Tange With Django 教程
    总结:
    django框架是一个web框架, 而且是一个后端框架程序, 它不是服务器, 需要注意
    django框架帮我们封装了很多的组件, 帮助我们实现各种功能, 具有很强的扩展性.

    3, 环境安装

    3.1. 创建虚拟环境

    和我们学习flask一样, 我们需要使用 virtualenvwrapper 帮我们创建一个单独的虚拟环境, 搭建项目.

    mkvirtualenv django_env -p python3
    mkvirtualenv : 创建一个新的虚拟环境
    django_env : 创建的新虚拟环境名称, 这个名称可以随意制定, 自己能看懂即可
    -p : 制定使用的python解释器版本
    python3 : 我们这里使用 python3 的解释器.
    注意: 这一步需要联网

    3.2. 安装Django

    使用django 1.11.11版本,注意需要联网

    pip install django==1.11.11
    

    pip : python 包管理器
    install : 安装
    django== 1.11.11 : 我们这里使用django1.11.11 这个版本, 现在最新的是 django 2.x的版本, 但是因为是最新的, 企业使用的不是很多, 所以我们这里还是使用1.x版本.

    3.3. 虚拟环境和pip的命令

    虚拟环境:

    创建虚拟环境

    mkvirtualenv 
    

    删除虚拟环境

    rmvirtualenv  
    

    进入虚拟环境、查看所有虚拟环境

    workon  
    

    退出虚拟环境

    deactivate  
    

    3.4 pip:

    安装依赖包

    pip install  
    

    卸载依赖包

    pip uninstall  
    

    查看已安装的依赖包

    pip list  
    

    冻结当前环境的依赖包

    pip freeze
    

    四. 创建工程

    在使用Flask框架时,项目工程目录的组织与创建是需要我们自己手动创建完成的。

    在django中,项目工程目录可以借助django提供的命令帮助我们创建。

    换句话说, 我们可以使用命令行, 直接生成一个项目模板, 我们可以基于这个模板来进行开发.

    4.1. 创建

    创建工程的命令为:

    生成一个django项目工程的使用方式:

    django-admin startproject 工程名称
    

    django-admin : django生成项目工程的命令
    startproject : 快速创建一个django项目, 使用这个命令可以快速下载一个项目模板, 在我们所在的目录
    工程名称 : 你想生成的项目名称, 这个名称可以随意定义
    例如:

    我们可以在桌面定义一个code目录, 在目录中:

    创建一个名为demo的项目工程,可执行如下命令:

    将目录切换到code中:

    cd ~/Desktop/code
    

    调用django项目生成命令,生成项目:

    django-admin startproject demo
    

    执行后,code目录中会多出一个新目录, 名为demo,此即为新创建的工程目录。

    这个新创建出来的目录,其实是我们下载的一个django开发模板, 我们可以在这个模板中继续django的开发.

    4.2. 工程目录说明

    我们可以看到刚刚生成的项目目录结构为:

    project_dir

    Snip20180803_2

    各个文件的作用:

    与项目同名的目录,此处为demo。
    settings.py 是项目的整体配置文件。
    urls.py 是项目的URL配置文件。
    wsgi.py 是项目与WSGI兼容的Web服务器入口。
    manage.py 是项目管理文件,通过它管理项目。

    4.3. 运行开发服务器

    在开发阶段,为了能够快速预览到开发的效果,django提供了一个纯python编写的轻量级web服务器,仅在开发阶段使用。

    我们可以通过命令行进入刚刚创建的项目目录中:

    进入创建的demo工程目录

    cd demo
    

    运行服务器命令如下:

    我们可以运行django提供的建议运行服务器来运行我们添加的代码

    python manage.py runserver IP地址:端口
    

    如果IP地址和端口号不想指定,可以使用系统默认提供的127.0.0.1的ip地址和8000的端口号

    上式就可以简写成:

    python manage.py runserver
    

    运行成功后命令行界面:
    runserver

    这里会看到一些红色的提示信息, 这些不是错误, 是提示我们有一些没有使用的迁移, 这里不用管它.

    查看运行效果:
    在浏览器中输入网址“127.0.0.1:8000”便可看到效果。

    runserver_browse

    总结:

    我们现在可以看到django框架已经运行起来了, 其中浏览器中看到的效果其实是django框架自动给我们生成的一个展示页面,这个页面的代码,在django代码中没有体现.
    我们现在使用的是django给我们提供的简易服务器, 这个服务器不能用于上线, 只能用于开发调试, 因为它对于多任务请求的支持性不强. 用于上线可能会出问题.
    这个简易服务器可以支持监听功能. 如果我们开启服务器, 并且修改了工程文件, 服务器能够监听我们的修改, 它会自动重启, 加载我们最新的修改. 方便我们的调试开发.
    如果我们想要在命令行停止当前服务器的运行, 可以敲: ctrl + c

    django默认工作在调式Debug模式下,如果增加、修改、删除文件,服务器会自动重启。

    django服务器运行成功后,项目中会多出一个服务器文件: db.sqlite3
    这是因为: django默认会对数据库进行支持, 如果我们没有配置数据库, 那么django会自己调用sqlite3这个数据库, 并且创建.

    五,pycharm 启动项目

    我们刚刚已经使用命令行的命令python manage.py runserver把项目跑起来了,

    但是没有使用pycharm运行当前项目, 如果想要使用pycharm运行当前项目, 需要配置一些信息, 如下所示:

    5.1. pycharm 打开当前项目:

    Snip20180803_6

    5.2. 打开后报错:

    Snip20180803_8

    报错原因以及解决方法:

    我们使用命令行创建的项目, 而不是使用pycharm创建的, 所以当前项目中的python解析器没有对应到虚拟环境(django_py3_1.11) 中的python版本上, 故报错.
    我们可以在pycharm的命令行中看出这一点: 命令行前面没有显示当前虚拟环境名称: ( django_py3_1.11 )
    我们需要切换当前pycharm项目的python解析器.

    5.3. 解决错误:

    Snip20180803_12

    Snip20180803_15

    配置完成之后, 我们会发现错误已经没有了, 也就是说我们把pycharm中的python解析器配置完成了:

    Snip20180803_16

    5.4. 运行项目:

    我们可以在manage.py文件中直接调用运行按钮来运行项目:

    Snip20180803_20

    出现的错误如何解决呢:

    Snip20180803_22

    我们现在再次运行项目:

    Snip20180803_26

    在这里插入图片描述总结:

    当前我们的django项目是使用命令行创建出来的,所以用pycharm运行,解析器可能不匹配,故我们需要重新配置解析器.
    其实django项目可以使用pycharm创建,但是这样创建出来的项目有很多我们用不到的配置文件,这些配置文件仅仅是为了支持pycharm的运行,对于最后的发布不利, 所以我们先使用命令行创建.
    这样的配置仅需要一次, 按照图示一步一步进行即可.

    六. 创建子应用

    在日常开发中, 我们会经常使用重复的代码, 所以我们可以对代码进行封装, 在不同的地方进行调用.

    同理: 如果一个项目中我们有很多的重复业务功能, 我们是否也可以对这些业务功能进行封装, 创建一个一个相对独立的模块来进行管理呢?

    故: django中推出了子应用的概念, 使用子应用来管理各个业务功能, 如果有重复的, 可以方便复制调用.

    在Flask框架中也有类似子功能应用模块的概念,即蓝图Blueprint。

    其中:

    Django的视图编写是放在子应用中的。

    6.1. 创建

    我们可以在项目的根目录下, 调用命令行, 创建子应用:

    创建子应用的常见命令:

    python manage.py startapp 子应用名称
    

    python : python3解释器
    manage.py : 上一章创建项目工程的时候, 生成的管理整个项目的文件
    startapp : 创建子应用的指令
    子应用名称 : 这个名称可以自己随意定, 一般会根据项目需求来指定.
    例如:

    在刚才创建的demo工程中,想要创建一个用户users子应用模块,可执行:

    进入项目的根目录中:

    cd ~/Desktop/code/demo
    

    执行生成子应用的指令, 生成一个叫users的子应用:

    python manage.py startapp users
    

    执行后,可以看到工程目录中多出了一个名为users的子目录。

    一般一个子应用代表一个模块, 例如: 购物车模块, 支付模块, 商品展示模块等…

    6.2. 子应用目录说明

    查看此时的工程目录,结构如下: app_dir

    Snip20180803_4
    在这里插入图片描述
    生成的子应用中各个文件的作用:

    admin.py 文件跟网站的后台管理站点配置相关。
    apps.py 文件用于配置当前子应用的相关信息。
    migrations 目录用于存放数据库迁移历史文件。
    models.py 文件用户保存数据库模型类。
    tests.py 文件用于开发测试用例,编写单元测试。
    views.py 文件用于编写Web应用视图。

    6.3. 配置子应用

    创建出来的子应用目录文件虽然被放到了工程项目目录中,但是django工程并不能立即直接使用该子应用,需要注册安装后才能使用。

    A. settings中默认的配置信息

    settings文件里, installed_apps列表中工程默认配置的信息:

    initial_installed_apps

    B. 添加子应用到settings中

    配置子应用信息也被称为: 注册安装一个子应用,

    即, 将子应用的配置信息文件apps.py中的Config类添加到INSTALLED_APPS列表中。

    例如:

    将刚创建的users子应用中apps.py文件的信息( users.apps.UsersConfig ), 添加到INSTALLED_APPS中, 如图所示:

    installed_apps

    使当前总的项目知道我们新添加的模块(子应用). 这样方便项目工程调用.

    总结:

    创建子应用的命令是: python manage.py startapp 子应用名称
    在公司开发过程中, 一个需求模块, 一般对应一个子应用, 例如: 购物车模块, 商品展示模块等.
    子应用的各个文件希望大家能够牢记:
    apps ======= 配置当前子应用的相关信息
    admin ======= 网站后台管理站点配置
    migrations === 存放数据库迁移历史文件
    models ====== 保存数据库模型类
    tests ======== 开发测试用例, 编写单元测试
    views ======= 编写web应用视图
    创建出来的子应用需要在项目工程的settings.py文件中进行配置,才可以使用,否则项目工程不知道添加的子应用模块.

    七. 创建视图

    同Flask框架一样,Django也用视图来编写Web应用的业务逻辑。

    Django的视图是定义在子应用的views.py中的。

    7.1. 创建

    打开刚创建的users模块,在views.py中编写视图代码。

    从django.http模块中导入HttpRespose

    from django.http import HttpResponse
    
    
    def index(request):
        """
        index视图
        :param request: 包含了请求信息的请求对象
        :return: 响应对象
        """
        return HttpResponse("hello the world!")
    

    说明:

    视图函数的第一个传入参数必须定义,用于接收Django构造的包含了请求数据的HttpReqeust对象,通常名为request。
    视图函数的返回值必须为一个响应对象,不能像Flask一样直接返回一个字符串,可以将要返回的字符串数据放到一个HTTPResponse对象中。

    7.2. 定义路由URL

    1) 在子应用中新建一个urls.py文件用于保存该应用的路由。

    new_urls_file

    2) 在users/urls.py文件中定义路由信息。

    从urls模块中导入url

    from django.conf.urls import url
    

    从当前目录导入我们的视图模块views

    from . import views
    

    urlpatterns是被django自动识别的路由列表变量

    urlpatterns = [
        # 每个路由信息都需要使用url函数来构造
        # url(路径, 视图)
        url(r'^index/$', views.index),
    ]
    

    3) 在工程总路由demo/urls.py中添加子应用的路由数据。

    from django.conf.urls import url, include
    from django.contrib import admin
    
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),  # django默认包含的,这个我们不用关心
        # 把子路由信息添加到总路由中
        url(r'^users/', include('users.urls')), 
    ]
    使用include来将子应用users里的全部路由包含进工程路由中;
    r'^users/' 决定了users子应用的所有路由都已/users/开头,如我们刚定义的视图index,其最终的完整访问路径为/users/index/。
    或者:
    
    include函数除了可以传递字符串之外,也可以直接传递应用的urls模块,如
    
    from django.conf.urls import url, include
    from django.contrib import admin
    
    import users.urls  # 先导入应用的urls模块
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
    
        # url(r'^users/', include('users.urls')),
        # 除了上面的写法以外,我们还可以写成下面的形式, 如果写成下面的形式的话
        # 需要导入当前的文件才可以
        url(r'^users/', include(users.urls)),  # 添加应用的路由
    ]
    

    4) 启动运行

    重新启动django程序

    python manage.py runserver
    

    在浏览器中输入网址127.0.0.1:8000/users/index/ 可看到返回的信息

    hello_the_world

    八,配置、静态文件与路由

    8.1. 配置文件

    1. BASE_DIR

    当前工程的根目录,Django会依此来定位工程内的相关文件,我们也可以使用该参数来构造文件路径。

    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    ___file___ : 可以理解为当前的文件
    os.path.abspath ( 文件 ) : 获取这个文件的绝对路径
    os.path.dirname( 路径 ) : 获取这个路径的上一级路径, 例如:
    path1 = os.path.dirname( 'c://home/setttings.py' )
    那么获取的结果为: path1 = 'c://home'
    os.path.dirname( 路径 ) : 再次获取这个路径的下一级路径.
    这样获取到的 BASE_DIR 其实就是当前项目的根目录.
    

    2.DEBUG

    设置是否为调试模式,创建工程后初始值为True,即默认工作在调试模式下。

    调试模式的作用:

    调试模式下django有个简易服务器在监听当前项目, 如果我们修改代码文件,服务器程序会自动重启, 重新加载修改过的文件 ( 方便开发 )

    当Django框架程序出现异常时,向前端(浏览器)显示详细的错误追踪信息,例如: ( 方便调试 )

    Snip20180803_10

    error_trackback

    注意:部署线上运行的Django不要运行在调式模式下,记得修改DEBUG=False。

    如果为非调试模式:

    程序出错后, 浏览器仅显示 500 的错误代码, 不会显示具体的错误信息:
    在这里插入图片描述

    3. 本地语言与时区

    Django支持本地化处理,即显示语言与时区支持本地化。

    本地化是将显示的语言、时间等使用本地的习惯,这里的本地化就是进行中国化,中国大陆地区使用简体中文,时区使用亚洲/上海时区,注意这里不使用北京时区表示。

    初始化的工程默认语言和时区为英语和UTC标准时区

    LANGUAGE_CODE = 'en-us'  # 语言: 英语
    TIME_ZONE = 'UTC'  # 时区: 协调世界时,又称世界统一时间、世界标准时间、国际协调时间
    将语言和时区修改为中国大陆信息
    
    LANGUAGE_CODE = 'zh-hans'
    TIME_ZONE = 'Asia/Shanghai'
    

    在这里插入图片描述
    注意:

    这里设置好时间之后, 我们需要把工程中添加的所有路径全部注释掉,才能够看到设置的中文效果生效.
    如果我们自己添加的路由信息不删除, 则django默认加载用户添加的信息, 进而不加载上面的界面, 换句话说, 如果你设置了路由, 则django不走它内部的默认页面, 而是走我们定义的路由界面,就看不到上面的中文画面了.

    8.2. 静态文件

    我们一般会把项目中的CSS、图片、js以及html等看做静态文件。

    静态文件我们会放在一个静态(static)文件夹中, 统一管理

    我们在html页面中调用时,需要指定静态文件的路径,故, Django中提供了一种用于配置静态文件路径的解析方式。

    静态文件可以放在项目根目录下,也可以放在应用的目录下,由于有些静态文件在项目中是通用的,所以推荐放在项目的根目录下,方便管理。

    为了提供静态文件访问路径,我们需要在项目的settings.py文件中配置两个参数:

    STATICFILES_DIRS : 存放查找静态文件的目录
    STATIC_URL : 访问静态文件的URL前缀
    

    例如:

    1) 在项目根目录下创建static_files目录来保存静态文件。

    如图:

    Snip20180803_13

    2) 在demo/settings.py中修改静态文件的两个参数为

    这个参数默认存在

    STATIC_URL = '/static/'
    

    我们可以添加这个参数, 用于补全静态文件路径

    STATICFILES_DIRS = [
        os.path.join(BASE_DIR, 'static_files'),
    ]
    

    3)此时在static_files添加的任何静态文件都可以使用网址 /static/文件在static_files中的路径 来访问了。

    例如:

    我们向static_files目录中添加一个index.html文件,在浏览器中就可以使用127.0.0.1:8000/static/index.html来访问:

    Snip20180803_14

    或者我们在static_files目录中添加了一个子目录和文件goods/detail.html,在浏览器中就可以使用127.0.0.1:8000/static/goods/detail.html来访问。

    注意

    Django 仅在调试模式下(DEBUG=True)能对外提供静态文件。

    当DEBUG=False工作在生产模式时,Django不再对外提供静态文件,需要是用collectstatic命令来收集静态文件并交由其他静态文件服务器来提供。(详细在部署时会讲)

    九路由说明

    view_process

    9.1. 路由定义位置

    Django的主要路由信息定义在工程同名目录下的urls.py文件中,该文件是Django解析路由的入口。

    每个子应用为了保持相对独立,可以在各个子应用中定义属于自己的urls.py来保存该应用的路由。然后用主路由文件包含各应用的子路由数据。

    除了上述方式外,也可将工程的全部路由信息都定义在主路由文件中,子应用不再设置urls.py。如:

    
    from django.conf.urls import url
    from django.contrib import admin
    # 导入子应用的视图模块
    import users.views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        # 添加子应用的路由信息,对应所对应的子应用视图方法
        url(r'^users/index/$', users.views.index)
    ]
    

    9.2. 路由解析顺序

    Django在接收到一个请求时,从主路由文件中的urlpatterns列表中以由上至下的顺序查找对应路由规则,如果发现规则为include包含,则再进入被包含的urls中的urlpatterns列表由上至下进行查询。

    值得关注的由上至下的顺序,有可能会使上面的路由屏蔽掉下面的路由,带来非预期结果。例如:

    urlpatterns = [
        url(r'^say', views.say),
        url(r'^sayhello', views.sayhello),
    ]
    

    即使访问sayhello/路径,预期应该进入sayhello视图执行,但实际优先查找到了say路由规则也与sayhello/路径匹配,实际进入了say视图执行。

    提示:
    需要注意定义路由的顺序,避免出现屏蔽效应。

    两种解决方法:
    第一种:

    # 调整书写顺序
    from django.conf.urls import url
    
    from . import views
    
    urlpatterns = [
        # 1. 调整书写顺序
        url(r'^sayhello', views.sayhello),
        url(r'^say', views.say)
    ]
    

    第二种:

    2.调整正则书写方式:
    
    from django.conf.urls import url
    
    from . import views
    
    urlpatterns = [
        # 2.调整正则:
        url(r'^say/$', views.say),
        url(r'^sayhello/$', views.sayhello)
    ]
    

    9.3. 路由命名与reverse反解析(逆向)

    3.1 路由命名

    在定义路由的时候,可以为路由命名,方便视图函数查找具体的某个路由。

    1) 在使用include函数定义路由时,可以使用namespace参数定义路由的命名空间,如
    url(r'^users/', include('users.urls', namespace='usersnamespace')),
    

    命名空间表示,凡是users.urls中定义的路由,均属于namespace指明的users名下。

    命名空间的作用:避免不同应用中的路由使用了相同的名字发生冲突,使用命名空间区别开。

    2) 在定义普通路由时,可以使用name参数指明路由的名字,如
    urlpatterns = [
        url(r'^index/$', views.index, name='indexname'),
        url(r'^say', views.say, name='sayname'),
    ]
    

    3.2 reverse反解析

    在视图函数中, 我们可以根据reverse进行反解析,获取当前视图函数的路径. 如:

    # 注意导包路径, 把reverse导入文件,进行反解析
    from django.core.urlresolvers import reverse 
    
    def index(request):
        return HttpResponse("hello the world!")
    
    def say(request):
        url = reverse('usersnamespace:indexname')  
        print(url)    # 打印: /users/index/
        return HttpResponse('say')
    

    补充:

    对于未指明namespace的,reverse(路由name)
    例如:
    只指定了name=‘indexname’, 没有指定namespace, 那么调用的时候可以写成:
    url = reverse(‘indexname’) 也可以获取到url的路径: /users/index/

    对于指明namespace的,reverse(命名空间namespace:路由name)
    例如:

    url(r'^users/', include(users.urls, namespace='indexnamespace'))
    url(r'^index/$', views.index, name='indexname')
    

    用reverse反解析:

    url = reverse('indexnamespace:indexname')
    

    最后获取的结果是:

    /users/index/
    

    9.4. 路径结尾斜线/的说明

    Django中定义路由时,通常以斜线/结尾,其好处是用户访问不以斜线/结尾的相同路径时,Django会把用户重定向到以斜线/结尾的路径上,而不会返回404不存在。

    例如:

    urlpatterns = [
        url(r'^index/$', views.index, name='index'),
    ]
    

    用户访问 index 或者 index/ 网址,均能访问到index视图。

    例如:

    用index/发送请求的效果:

    Snip20180804_1

    再例如:

    使用 index发送请求的情况:

    Snip20180804_2

    补充说明:

    虽然路由结尾带/能带来上述好处,但是却违背了HTTP中URL表示资源位置路径的设计理念。

    是否结尾带/以所属公司定义风格为准。

    十, App应用配置

    在每个应用目录中都包含了apps.py文件,用于保存该应用的相关信息。

    在创建应用时,Django会向apps.py文件中写入一个该应用的配置类,如

    from django.apps import AppConfig
    
    class UsersConfig(AppConfig):
        name = 'users'
    

    我们将此类添加到工程settings.py中的INSTALLED_APPS列表中,表明注册安装具备此配置属性的应用。

    AppConfig.name 属性表示这个配置类是加载到哪个应用的,每个配置类必须包含此属性,默认自动生成。

    AppConfig.verbose_name 属性用于设置该应用的直观可读的名字,此名字在Django提供的Admin管理站点中会显示,如

      from django.apps import AppConfig
    
      class UsersConfig(AppConfig):
          name = 'users'
          verbose_name = '用户管理'
    

    所以: 一般我们会在 UsersConfig 文件中添加上 verbose_name 属性, 为admin管理站点提供应用的信息.

    展开全文
  • Django框架全面讲解

    万次阅读 多人点赞 2018-01-21 22:11:29
    Python的WEB框架有Django、Tornado、Flask 等多种,Django相...本文将以下方面带大家全面了解Django框架,笔者使用的版本为1.10. 流程 基本配置路由系统视图view模板Model中间件Form认证系统CSRF分页CookieSees

    Python的WEB框架有Django、Tornado、Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能。

    本文将以下方面带大家全面了解Django框架,笔者使用的版本为1.10.

    1. 流程

    2. 基本配置
    3. 路由系统
    4. 视图view
    5. 模板
    6. Model
    7. 中间件
    8. Form
    9. 认证系统
    10. CSRF
    11. 分页
    12. Cookie
    13. Seesion
    14. 缓存
    15. 序列化
    16. 信号
    17. admin

    一、 Django流程介绍

     

    MVC是众所周知的模式,即:将应用程序分解成三个组成部分:model(模型),view(视图),和 controller(控制 器)。其中:
          M——管理应用程序的状态(通常存储到数据库中),并约束改变状态的行为(或者叫做“业务规则”)。
          C——接受外部用户的操作,根据操作访问模型获取数据,并调用“视图”显示这些数据。控制器是将“模型”和“视图”隔离,并成为二者之间的联系纽带。
          V——负责把数据格式化后呈现给用户。

    Django也是一个MVC框架。但是在Django中,控制器接受用户输入的部分由框架自行处理,所以 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),称为 MTV模式:

        M 代表模型(Model),即数据存取层。 该层处理与数据相关的所有事务: 如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。

        T 代表模板(Template),即表现层。 该层处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。

        V 代表视图(View),即业务逻辑层。 该层包含存取模型及调取恰当模板的相关逻辑。 你可以把它看作模型与模板之间的桥梁。

     

    二、 Django 基本配置

    1. 创建django程序

    • 终端命令:django-admin startproject sitename  (在当前目录下创建一个Django程序)
    • IDE创建Django程序时,本质上都是自动执行上述命令

    其他常用命令:

      python manage.py runserver ip:port  (启动服务器,默认ip和端口为http://127.0.0.1:8000/)

      python manage.py startapp appname  (新建 app)

      python manage.py syncdb  (同步数据库命令,Django 1.7及以上版本需要用以下的命令)

      python manage.py makemigrations  (显示并记录所有数据的改动)

      python manage.py migrate  (将改动更新到数据库)

      python manage.py createsuperuser  (创建超级管理员)

      python manage.py dbshell  (数据库命令行)

      python manage.py  (查看命令列表)

     

    2. 程序目录

     

    3. 配置文件

    a、数据库

    支持SQLite 3(默认)、PostgreSQL 、MySQL、Oracle数据库的操作

     具体配置

    Django框架对于开发者而言高度透明化,对于不同数据库的具体使用方法是一致的,改变数据库类型只需要变动上述配置即可。

    想要了解更多请戳这里

     

    b、静态文件添加

     settings配置

     

    三、 Django 路由系统

    URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。URL的加载是从配置文件中开始。

    参数说明:

    • 一个正则表达式字符串
    • 一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
    • 可选的要传递给视图函数的默认参数(字典形式)
    • 一个可选的name参数

     

    1. 示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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/ 不会匹配上面列表中的任何条目, 因为第三条的月份需要二位数字.
    • /articles/2003/ 会匹配上第一条而不是第二条,因为匹配是按照从上到下顺序而进行的, Django 会调用函数 views.special_case_2003(request)
    • /articles/2003 不会匹配上面列表中的任何条目, 因为每个URL应该以 / 结尾.
    • /articles/2003/03/03/ 会匹配上最后一条. Django 会调用函数 views.article_detail(request, '2003', '03', '03').

     

    2. 命名组(Named groups)

    在上面的简单例子中,并没有使用正则表达式分组,在更高级的用法中,很有可能使用正则分组来匹配URL并且将分组值通过参数传递给view函数。

    在Python的正则表达式中,分组的语法是 (?P<name>pattern), name表示分组名,pattern表示一些匹配正则.

    这里是一个简单的小例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 正则知识
    import re
     
    ret=re.search('(?P<id>\d{3})/(?P<name>\w{3})','weeew34ttt123/ooo')
     
    print(ret.group())
    print(ret.group('id'))
    print(ret.group('name'))
    -------------------------------------
    123/ooo
    123
    ooo

      

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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),
    ]

    For example:

    • A request to /articles/2005/03/ 会调用函数 views.month_archive(request, year='2005',month='03'), 而不是 views.month_archive(request, '2005', '03').
    • A request to /articles/2003/03/03/ 会调用函数 views.article_detail(request, year='2003',month='03', day='03').

    常见写法实例:

     

    3. 二级路由(Including)

    那如果映射 url 太多怎么办,全写一个在  urlpatterns 显得繁琐,so 二级路由应用而生

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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)),
    ]

    在上面这个例子中,如果请求url为 /credit/reports/ 则会调用函数 credit_views.report().

     

    使用二级路由也可以减少代码冗余,使代码更加简洁易懂

      

    4. 添加额外的参数

    URLconfs 有一个钩子可以让你加入一些额外的参数到view函数中.

    1
    2
    3
    4
    5
    6
    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 将会调用函数l views.year_archive(request, year='2005',foo='bar').

    需要注意的是,当你加上参数时,对应函数views.year_archive必须加上一个参数,参数名也必须命名为 foo,如下:

     

    1
    2
    3
    def year_archive(request, foo):
        print(foo)
        return render(request, 'index.html')

      

    5. 别名的使用

    1
    url(r'^index',views.index,name='bieming')

    url中还支持name参数的配置,如果配置了name属性,在模板的文件中就可以使用name值来代替相应的url值.

    我们来看一个例子:

     name的应用

      

    6. 指定view的默认配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 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 值由正则表达式捕获。

     

    四、 Django Views(视图函数)

    http请求中产生两个核心对象:

      http请求:HttpRequest对象

      http响应:HttpResponse对象

     

    1. HttpRequest对象

    当请求一个页面时,Django 创建一个 HttpRequest对象包含原数据的请求。然后 Django 加载适当的视图,通过 HttpRequest作为视图函数的第一个参数。每个视图负责返回一个HttpResponse目标。

    复制代码
    path:       请求页面的全路径,不包括域名
    
    method:     请求中使用的HTTP方法的字符串表示。全大写表示。例如
    
                       if  req.method=="GET":
    
                                 do_something()
    
                       elseif req.method=="POST":
    
                                 do_something_else()
    
    GET:         包含所有HTTP GET参数的类字典对象
    
    POST:       包含所有HTTP POST参数的类字典对象
    
                 服务器收到空的POST请求的情况也是可能发生的,也就是说,表单form通过
                 HTTP POST方法提交请求,但是表单中可能没有数据,因此不能使用
                 if req.POST来判断是否使用了HTTP POST 方法;应该使用  if req.method=="POST"
    
    
    
    COOKIES:     包含所有cookies的标准Python字典对象;keys和values都是字符串。
    
    FILES:      包含所有上传文件的类字典对象;FILES中的每一个Key都是<input type="file" name="" />标签中 
                name属性的值,FILES中的每一个value同时也是一个标准的python字典对象,包含下面三个Keys:
    
                filename:      上传文件名,用字符串表示
                content_type:   上传文件的Content Type
                content:       上传文件的原始内容
    
    
    user:       是一个django.contrib.auth.models.User对象,代表当前登陆的用户。如果访问用户当前
                 没有登陆,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你
                 可以通过user的is_authenticated()方法来辨别用户是否登陆:
                 if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware
                 时该属性才可用
    
    session:    唯一可读写的属性,代表当前会话的字典对象;自己有激活Django中的session支持时该属性才可用。
    
    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          – 服务器的端口(一个字符串)。
    复制代码

     

    2. HttpResponse对象

    对于HttpRequest对象来说,是由django自动创建的,但是,HttpResponse对象就必须我们自己创建。每个view请求处理方法必须返回一个HttpResponse对象。

    在HttpResponse对象上扩展的常用方法:

    • 页面渲染:render(推荐),render_to_response,
    • 页面跳转:redirect
    • locals:   可以直接将对应视图函数中所有的变量传给模板    

    值得注意的是对于页面渲染的方法中,render和render_to_response使用方法和功能类似,但是render功能更为强大,推荐使用

     

    3. 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')
    复制代码

     

    五、 模板

    1. 模板的执行

    模版的创建过程,对于模版,其实就是读取模版(其中嵌套着模版标签),然后将 Model 中获取的数据插入到模版中,最后将信息返回给用户。

     示例

     

    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 }}

     小知识点:在模板语言中字典数据类型的取值是通过dict.xxx而不是dict[xxx]

     

    3. 自定义标签

    因为在模板语言中不能够做运算等一些稍显复杂的操作,所以在Django中提供了两种自定制标签,一种是simple_tag,一种是filter。

    simple_tag: 任意传递参数,但是不能用作布尔判断

    filter: 最多只能传递二个参数,可以用作布尔判断

    在这里着重介绍simple_tag类型,filter的实现类似

    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

     示例

    更多见文档:https://docs.djangoproject.com/en/1.10/ref/templates/language/

     

    六、 Model

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

    django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表。

    关系对象映射(Object Relational Mapping,简称ORM)。

     

    1. 创建表

    a、基本结构

    1
    2
    3
    4
    5
    6
    from django.db import models
        
     class userinfo(models.Model):
        name = models.CharField(max_length=30)
        email = models.EmailField()
        memo = models.TextField()
    复制代码
    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
    复制代码
    复制代码
    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 文件
    复制代码
    复制代码
    class UserInfo(models.Model):
            nid = models.AutoField(primary_key=True)
            username = models.CharField(max_length=32)
            class Meta:
                # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
                db_table = "table_name"
    
                # 联合索引
                index_together = [
                    ("pub_date", "deadline"),
                ]
    
                # 联合唯一索引
                unique_together = (("driver", "restaurant"),)
    
                # admin中显示的表名称
                verbose_name
    
                # verbose_name加s
                verbose_name_plural
            
        更多:https://docs.djangoproject.com/en/1.10/ref/models/options/
    复制代码
    复制代码
    1.触发Model中的验证和错误提示有两种方式:
            a. Django Admin中的错误信息会优先根据Admiin内部的ModelForm错误信息提示,如果都成功,才来检查Model的字段并显示指定错误信息
            b. 调用Model对象的 clean_fields 方法,如:
                # models.py
                class UserInfo(models.Model):
                    nid = models.AutoField(primary_key=True)
                    username = models.CharField(max_length=32)
    
                    email = models.EmailField(error_messages={'invalid': '格式错了.'})
    
                # views.py
                def index(request):
                    obj = models.UserInfo(username='11234', email='uu')
                    try:
                        print(obj.clean_fields())
                    except Exception as e:
                        print(e)
                    return HttpResponse('ok')
    
               # Model的clean方法是一个钩子,可用于定制操作,如:上述的异常处理。
    
        2.Admin中修改错误提示
            # admin.py
            from django.contrib import admin
            from model_club import models
            from django import forms
    
    
            class UserInfoForm(forms.ModelForm):
                username = forms.CharField(error_messages={'required': '用户名不能为空.'})
                email = forms.EmailField(error_messages={'invalid': '邮箱格式错误.'})
                age = forms.IntegerField(initial=1, error_messages={'required': '请输入数值.', 'invalid': '年龄必须为数值.'})
    
                class Meta:
                    model = models.UserInfo
                    # fields = ('username',)
                    fields = "__all__"
    
    
            class UserInfoAdmin(admin.ModelAdmin):
                form = UserInfoForm
    
    
            admin.site.register(models.UserInfo, UserInfoAdmin)
    复制代码

     

    b、连表结构

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

    应用场景:

    • 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)
      例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。
    • 多对多:在某表中创建一行数据是,有一个可以多选的下拉框
      例如:创建用户信息,需要为用户指定多个爱好
    • 一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了
      例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据
     字段以及参数

     

    2. 操作表

    a、基本操作

     基本操作

     

    b、进阶操作(了不起的双下划线

    利用双下划线将字段和对应的操作连接起来

    复制代码
    # 获取个数
            #
            # models.Tb1.objects.filter(name='seven').count()
    
            # 大于,小于
            #
            # models.Tb1.objects.filter(id__gt=1)              # 获取id大于1的值
            # models.Tb1.objects.filter(id__gte=1)              # 获取id大于等于1的值
            # models.Tb1.objects.filter(id__lt=10)             # 获取id小于10的值
            # models.Tb1.objects.filter(id__lte=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
    
            # isnull
            # Entry.objects.filter(pub_date__isnull=True)
    
            # 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='seven').order_by('id')    # asc
            # models.Tb1.objects.filter(name='seven').order_by('-id')   # desc
    
            # 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"
    
            # limit 、offset
            #
            # models.Tb1.objects.all()[10:20]
    
            # regex正则匹配,iregex 不区分大小写
            #
            # Entry.objects.get(title__regex=r'^(An?|The) +')
            # Entry.objects.get(title__iregex=r'^(an?|the) +')
    
            # date
            #
            # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
            # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))
    
            # year
            #
            # Entry.objects.filter(pub_date__year=2005)
            # Entry.objects.filter(pub_date__year__gte=2005)
    
            # month
            #
            # Entry.objects.filter(pub_date__month=12)
            # Entry.objects.filter(pub_date__month__gte=6)
    
            # day
            #
            # Entry.objects.filter(pub_date__day=3)
            # Entry.objects.filter(pub_date__day__gte=3)
    
            # week_day
            #
            # Entry.objects.filter(pub_date__week_day=2)
            # Entry.objects.filter(pub_date__week_day__gte=2)
    
            # hour
            #
            # Event.objects.filter(timestamp__hour=23)
            # Event.objects.filter(time__hour=5)
            # Event.objects.filter(timestamp__hour__gte=12)
    
            # minute
            #
            # Event.objects.filter(timestamp__minute=29)
            # Event.objects.filter(time__minute=46)
            # Event.objects.filter(timestamp__minute__gte=29)
    
            # second
            #
            # Event.objects.filter(timestamp__second=31)
            # Event.objects.filter(time__second=2)
            # Event.objects.filter(timestamp__second__gte=31)
    复制代码

     

    c、其他操作

    复制代码
    # extra
        #
        # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
        #    Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
        #    Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
        #    Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
        #    Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])
    
        # F
        #
        # from django.db.models import F
        # models.Tb1.objects.update(num=F('num')+1)
    
    
        # Q
        #
        # 方式一:
        # Q(nid__gt=10)
        # Q(nid=8) | Q(nid__gt=10)
        # Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
        # 方式二:
        # 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)
    
    
        # 执行原生SQL
        #
        # from django.db import connection, connections
        # cursor = connection.cursor()  # cursor = connections['default'].cursor()
        # cursor.execute("""SELECT * from auth_user where id = %s""", [1])
        # row = cursor.fetchone()
    复制代码

     

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

    利用双下划线和 _set 将表之间的操作连接起来

     表结构实例
     一对一操作
     一对多
     多对多操作

     

    扩展:

    a、自定义上传

    复制代码
    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')
    复制代码

    b、Form上传文件实例

    复制代码
    # HTML
    
           <form method="post" action="/view1/" enctype="multipart/form-data">
               <input type="file" name="ExcelFile" id="id_ExcelFile" />
               <input type="submit" value="提交" />
           </form>
    
    
    
    # Form
    
    class FileForm(forms.Form):
        ExcelFile = forms.FileField()
    
    # Models
    
    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)
    
    # Views
    
    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
    复制代码

    c、ajax上传文件实例

    复制代码
    <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>
    复制代码
    class FileForm(forms.Form):
        ExcelFile = forms.FileField()
    复制代码
    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)
    复制代码
    复制代码
    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())
    复制代码

     

    七、中间件(MiddleWare)

    django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。

    在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,如下图。

    与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)

    分析源码得知前二个方法是从前往后执行的,后三个方法是从后往前执行的

     所以前两个方法是请求进来时要穿越的,而后三个方法是请求出去时要穿越的

    一张图告诉你中间件的运行流程

     

    自定义中间件

    1、创建中间件类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Middle_Test(object):
           
        def process_request(self,request):
            pass
        def process_view(self, request, callback, callback_args, callback_kwargs):
            =1
            pass
        def process_exception(self, request, exception):
            pass
           
        def process_response(self, request, response):
            return response

      

    2、注册中间件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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',
        'sparks.middleware.auth.Middle_Test',
    )

      

    八、 Form

    django中的Form一般有两种功能:

    • 输入html
    • 验证用户输入
     Form
     示例

     

    利用Form还可以自动生成前端的input标签:

     form.py
     views.py
     form1.html

     

    扩展:ModelForm

    在使用Model和Form时,都需要对字段进行定义并指定类型,通过ModelForm则可以省去From中字段的定义

     ModelForm

     

     

     

    九、 认证系统(auth)

    auth模块是Django提供的标准权限管理系统,可以提供用户身份认证, 用户组管理,并且可以和admin模块配合使用.

    在INSTALLED_APPS中添加'django.contrib.auth'使用该APP, auth模块默认启用.

    model

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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指定的位置.

    若未指定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):
        ...
    复制代码
    复制代码

     

     

    十、 跨站请求伪造(csrf)

    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

      在Django1.10中,为了防止BREACH攻击,对cookie-form类型的csrf做了一点改进,即在cookie和form中的token值是不相同的

     

    应用

    1、普通表单

    1
    2
    3
    4
    5
    veiw中设置返回值:
         return render(request, 'xxx.html', data)
       
    html中设置Token:
      {% csrf_token %}

      

    2、Ajax

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

     view.py
     text.html

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

     

    十一、 分页

    1. Django内置分页

     views.py
     Html
     扩展内置分页:views.py
     扩展内置分页:Html

    2. 自定义分页

    分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该在数据库表中的起始位置。

    1、设定每页显示数据条数

    2、用户输入页码(第一页、第二页...)

    3、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置

    4、在数据表中根据起始位置取值,页面上输出数据


    需求又来了,需要在页面上显示分页的页面。如:[上一页][1][2][3][4][5][下一页]

    1、设定每页显示数据条数

    2、用户输入页码(第一页、第二页...)

    3、设定显示多少页号

    4、获取当前数据总条数

    5、根据设定显示多少页号和数据总条数计算出,总页数

    6、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置

    7、在数据表中根据起始位置取值,页面上输出数据

    8、输出分页html,如:[上一页][1][2][3][4][5][下一页]

     分页实例

    总结,分页时需要做三件事:

    • 创建处理分页数据的类
    • 根据分页数据获取数据
    • 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]

     

    十二、 Cookie

    1. 获取Cookie:

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

    2. 设置Cookie:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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。

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

     

    十三、 Session

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

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

    1、数据库Session

     View Code

    2、缓存Session

     View Code

    3、文件Session

     View Code

    4、缓存+数据库Session

     View Code

    5、加密cookie Session

     View Code

    跟数据库的操作一样,在Django中不同缓存方式的使用方法是一致的,想要改变缓存的类型只需要改变上述相应配置即可。

    更多参考:猛击这里 和 猛击这里

    扩展:Session用户验证(装饰器)

    1
    2
    3
    4
    5
    6
    7
    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

      

    十四、 缓存

    由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。

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

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

    和数据库类似,缓存的具体操作都是一样的,使用不同的方式只需要将配置改掉即可

    1、配置

    a、开发调试

     View Code

    b、内存

     View Code

    c、文件

     View Code

    d、数据库

     View Code

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

     View Code

    f、Memcache缓存(pylibmc模块)

     View Code

     

    2、应用

    a. 全站使用

     View Code

    b. 单独视图缓存

     View Code

    c、局部视图使用

     View Code

    注:如果出现多个url匹配同一个view函数的情况,缓存机制会根据每一个不同的url做单独的缓存

    更多:猛击这里

     

     

    十五、 序列化

    关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求一般返回的为Json格式。

    1. serializers

    1
    2
    3
    4
    5
    from django.core import serializers
     
    ret = models.BookType.objects.all()
     
    data = serializers.serialize("json", ret)

    2. json.dumps

    1
    2
    3
    4
    5
    6
    7
    8
    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日期,所以可以通过自定义处理器来做扩展,如:

     自定义示例

     

    十六、 信号

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

    1、Django内置信号

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    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内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:

     View Code

     

    2、自定义信号

    a. 定义并注册信号

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 自定制信号
    import django.dispatch
    pizza_done = django.dispatch.Signal(providing_args=["toppings""size"])
     
    def callback(sender, **kwargs):
        print("self-define")
        print(sender, kwargs)
     
    pizza_done.connect(callback)

      

    b. 触发信号

    1
    2
    3
    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后台管理页面

    注:不建议新手经常使用admin,会形成依赖,核心的是model模块的操作!

    1、创建后台管理员

    python manage.py createsuperuser

    2、配置后台管理url(默认已配)

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

    3、注册和配置django admin 后台管理页面

    a、在admin中执行如下配置
     View Code
    b、设置数据表名称
     View Code
    c、打开表之后,设定默认显示,需要在model中作如下配置
     View Code
    d、为数据表添加搜索功能
     View Code
    e、添加快速过滤
     View Code

    更多:https://docs.djangoproject.com/en/1.11/ref/contrib/admin/


    展开全文
  • 2小时上手Django框架

    千人学习 2019-09-29 15:48:16
    Django因其丰富的组件、高度的稳定性、强大的后台管理,在Python Web开发上占有绝大的市场份额与地位,2小时上手Django框架、帮助学员最快速的理解Web的运行原理和Django环境的快速搭建,并通过Django的Admin,一键...
  • Python之Django框架的使用

    千次阅读 2018-10-04 18:25:34
    1、安装Django pip install django 2、创建Django项目 django-admin startproject 项目名称 3、在setting文件中配置数据库 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME...

    1、安装Django

    pip install django
    

    2、创建Django项目

    django-admin startproject 项目名称
    

    3、在setting文件中配置数据库

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

    4、创建应用

    python manage.py startapp 应用名称
    

    5、定义模型类models.py,一个类对应数据库的一个表,一个属性,对应数据表中的一个字段

    from django.db import models
    
    class 类名(models.Model):
      xxxx=models.CharField(max_length=20)
      。。。
    

    6、生成数据表

    • 激活模型:编辑settings.py文件,将应用加入到installed_apps中
    • 生成迁移文件:根据模型类生成sql语句
      python manage.py makemigrations
    • 执行迁移:执行sql语句生成数据表
      python manage.py migrate

    7、运行Django项目,默认端口8000

    python manage.py runserver ip:port
    

    8、使用Django的管理

    • 创建一个管理员用户
    python manage.py createsuperuser,按提示输入用户名、邮箱、密码
    
    • 启动服务器,通过“127.0.0.1:8000/admin”访问,输入上面创建的用户名、密码完成登录
    • 进入管理站点,默认可以对groups、users进行管理

    9、管理界面本地化

    • 编辑settings.py文件,设置编码、时区
    LANGUAGE_CODE = 'zh-Hans'
    TIME_ZONE = 'Asia/Shanghai'
    

    10、向admin注册应用的模型

    • 打开admin.py文件,注册模型

      from django.contrib import admin
      from models import xxx
      admin.site.register(xxx)

    11、视图

    • 在django中,视图对WEB请求进行回应
    • 视图接收reqeust对象作为第一个参数,包含了请求的信息
    • 视图就是一个Python函数,被定义在views.py中
    #coding:utf-8
    from django.http import HttpResponse
    
    def index(request):
        return HttpResponse("index")
    
    • 定义完成视图后,需要配置urlconf,否则无法处理请求

    12、模板

    • 模板是html页面,可以根据视图中传递的数据填充值
    • 修改settings.py文件,设置TEMPLATES的DIRS值
    'DIRS': [os.path.join(BASE_DIR, 'templates')],
    
    • 在模板中访问视图传递的数据
    {{输出值,可以是变量,也可以是对象.属性}}
    {%执行代码段%}
    
    <!DOCTYPE html>
    <html>
    <head>
      <title></title>
    </head>
    <body>
    
        {{xxx}}
    
    </body>
    </html>
    

    13、使用模板

    • 编辑views.py文件,在方法中调用模板
    from django.http import HttpResponse
    from django.template import RequestContext, loader
    from models import xxx
    
    def index(request):
        booklist = BookInfo.objects.all()
        template = loader.get_template('xxx.html')
        context = RequestContext(request, {'xxx': xxx})
        return HttpResponse(template.render(context))
        
    def detail(reqeust, id):
        xxx = BookInfo.objects.get(pk=id)
        template = loader.get_template(xxx.html')
        context = RequestContext(reqeust, {'xxx': xxx})
        return HttpResponse(template.render(context))
    

    14、Render

    • Django提供了函数Render()