Django框架简介

框架(framework),指为解决一个开放性的问题而设计的具有一 定约束性的支撑结构,使用框架可以帮助你快速开发特定的系统。

常见的python web框架
`Full-Stack Framework`(全栈框架)
Django、web2py、TurboGears、Pylons、......

`Non Full-Stack Framework`(非全栈框架)
tornado、Flask、Bottle、webpy、pyramid.....

部署Django环境

python 3.5.2
Django==1.11.5
PyMySQL==0.7.11
pytz==2017.2

下载安装Django模块

  • 方法一:使用pip工具

    更新pip的版本

    python -m pip install --upgrade pip

    首先要确保安装了pip工具

     pip install Django
  • 方法二:使用git

    $ git clone git://github.com/django/django.git
    $ pip install -e django/
    
  • 方法三:下载Django的py包,然后使用python命令安装

  • 检测是否安装成功

    In [1]: import django
    
    In [2]: django.VERSION
    Out[2]: (1, 11, 4, u'final', 0)
    

安装数据库

django默认提供了Sqlite数据库

安装python和mysql的连接模块。

pip  install PyMySQL     连接数据库

启动Apache

Django-admin命令

>django-admin.py help

Type 'django-admin.py help 

查看指定命令的帮助文档

>django-admin.py help startproject

usage: django-admin.py startproject [-h] [--version] [-v {0,1,2,3}]
                                    [--settings SETTINGS]
                                    [--pythonpath PYTHONPATH] [--traceback]
                                    [--no-color] [--template TEMPLATE]
                                    [--extension EXTENSIONS] [--name FILES]
                                    name [directory]

Creates a Django project directory structure for the given project name in th
current directory or optionally in the given directory.

positional arguments:
  name                  Name of the application or project.
  directory             Optional destination directory

optional arguments:
  -h, --help            show this help message and exit

创建Django第一个app(helloworld)

[root@miner-k ~]# mkdir /app
[root@miner-k ~]# cd /app/
[root@miner-k app]# django-admin  startproject mysite

[root@miner-k app]# tree .
.
└── mysite                 #Django项目的名称,刚才创建的项目名称
    ├── manage.py          #命令行实用程序,与Django进行交互。
    └── mysite
        ├── __init__.py
        ├── settings.py      #配置文件
        ├── urls.py          #url的设置
        └── wsgi.py          #动态网关接口文件

Django-admin.py是Django的一个用于管理任务的命令工具,manage.py是对Django-admin.py的简单包装,每一个Django project里面都会包含一个manage.py

[root@miner-k mysite]# python manage.py help

Type 'manage.py help ' for help on a specific subcommand.

Available subcommands:

[auth]
    changepassword
    createsuperuser

[contenttypes]
    remove_stale_contenttypes

[django]
    check
    compilemessages
    createcachetable
    dbshell
    diffsettings

创建一个名为hello的app

[root@miner-k mysite]# python manage.py startapp hello

一般不同的APP负责不同的功能,一个app负责一个功能。

[root@miner-k mysite]# tree hello/
blog/
├── admin.py            #管理后台的配置
├── apps.py         #app的配置
├── __init__.py
├── migrations          #数据库的管理
│   └── __init__.py
├── models.py           #模型代码的配置
├── tests.py            #单元测试
└── views.py            #业务代码

登录到Django的后台

  1. 生成同步数据库的脚本

    D:\pythonwork\django\mysite>python manage.py makemigrations
    No changes detected
    
  2. 同步数据

    D:\pythonwork\django\mysite>python manage.py migrate
    Operations to perform:
      Apply all migrations: admin, auth, contenttypes, sessions
    Running migrations:
      Applying contenttypes.0001_initial... OK
      Applying auth.0001_initial... OK
      Applying admin.0001_initial... OK
      auth.0007_alter_validators_add_error_messages... OK
      Applying auth.0008_alter_user_username_max_length... OK
      Applying sessions.0001_initial... OK
  3. 创建超级用户以及密码(密码不能太短)

    D:\pythonwork\django\mysite>python35 manage.py createsuperuser
    Username (leave blank to use 'administrator'): admin
    Email address:
    Password:
    Password (again):
    Superuser created successfully.
  4. 修改超级用户的密码

    D:\pythonwork\django\mysite>python35 manage.py changepassword admin
    Changing password for user 'admin'
    Password:
    
  5. 启动服务

    D:\pythonwork\django\mysite>python35 manage.py runserver
    
    Performing system checks...
    
    System check identified no issues (0 silenced).
    October 10, 2017 - 20:52:07
    Django version 1.11.5, using settings 'mysite.settings'
    Starting development server at http://127.0.0.1:8000/
    Quit the server with CTRL-BREAK.
  6. 登录后台
    登录后台的URL:http://127.0.0.1:8000/admin/

设置服务监控的端口

启动的时候指定监听的端口

D:\pythonwork\django\mysite>python35 manage.py runserver 8080
Performing system checks...

System check identified no issues (0 silenced).
September 12, 2017 - 22:13:32
Django version 1.11.5, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8080/
Quit the server with CTRL-BREAK.

创建一个网页

静态文件存放到app的目录下

默认情况下
static 目录:存放css、js、图片等静态文件
templates 目录:存放模板

Django框架简介_第1张图片

在app中配置

  1. 修改hello的app目录下的views.py定义一个业务请求处理的函数

    from django.shortcuts import render
    
    
    # Create your views here.
    
    def hello(request):
        return  render(request,'table.html ')
  2. 定义一个模板并引用静态文件

    在app的目录下创建两个目录statictemplates
    将static目录下存放CSS、js格式的文件
    在template目录下存放table.html文件

在项目mysite目录中配置

  1. 在settings.py里面的INSTALLED_APPS中加入hello,将新建的app增加到项目中。

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'hello',
    ]
    
  2. 在urls.py里面定义url地址

    
    from django.conf.urls import url
    from django.contrib import admin
    from hello import views          #从指定的app中导入views
    '''url(URL路径正则表达式,app中views的函数,别名)'''   
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^hello/', views.hello,name='hello'),
    ]

启动服务

访问测试
访问网站:http://127.0.0.1:8000/hello/

静态文件、模板存放到工程目录下

Django框架简介_第2张图片

修改seting.py文件

'''在DIRS中指定模板的目录'''

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]


'''指定静态文件的目录'''
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)

在app中设置URL

上面的URL的配置是在工程的urls.py中设置访问的URL,现在为了方便管理不同的URL,需要在不同的app下设置URL

工程中的urls.py配置

''' 包含app中URL的配置文件
    1.导入incloude():
        from django.conf.urls import url, include
    2. 增加URL的参数:  
        url(r'^blog/', include('blog.urls'))
        r'^blog/' :访问的后缀
        include('blog.urls'):指定包含的URL的存放位置。blog目录下的urls
'''
from django.conf.urls import url,include
from django.contrib import admin


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include('hello.urls')),
]

app中的urls.py的配置

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


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

注意:访问URL时,URL是项目中URL中配置加app中的URL。如果在工程中的URl中设置url(r'^abc/', include('hello.urls')),在app中设置url(r'^hello/$', views.hello),访问时输入的URl为http://127.0.0.1:8000/abc/hello/

MTV和MVC

在钻研更多代码之前,让我们先花点时间考虑下 Django 数据驱动 Web 应用的总体设计。

Django 的设计鼓励松耦合及对应用程序中不同部分的严格分割。 遵循这个理念的话,要想修改应用的某部分而不影响其它部分就比较容易了。 在视图函数中,我们已经讨论了通过模板系统把业务逻辑和表现逻辑分隔开的重要性。 在数据库层中,我们对数据访问逻辑也应用了同样的理念。

Django框架简介_第3张图片

把数据存取逻辑、业务逻辑和表现逻辑组合在一起的概念有时被称为软件架构的 Model-View-Controller (MVC)模式。 在这个模式中, Model 代表数据存取层,View 代表的是系统中选择显示什么和怎么显示的部分,Controller 指的是系统中根据用户输入并视需要访问模型,以决定使用哪个视图的那部分。

Django 紧紧地遵循这种 MVC 模式,可以称得上是一种 MVC 框架。 以下是 Django 中 M、V 和 C 各自的含义:

  • M ,数据存取部分,由django数据库层处理。
  • V ,选择显示哪些数据要显示以及怎样显示的部分,由视图和模板处理。
  • C ,根据用户输入委派视图的部分,由 Django 框架根据 URLconf 设置,对给定 URL 调用适当的 Python 函数。

由于 C 由框架自行处理,而 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),Django 也被称为 MTV 框架 。在MTV 开发模式中:

  • M 代表模型(Model),即数据存取层。 该层处理与数据相关的所有事务: 如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。
  • T 代表模板(Template),即表现层。 该层处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。
  • V 代表视图(View),即业务逻辑层。 该层包含存取模型及调取恰当模板的相关逻辑。 你可以把它看作模型与模板之间的桥梁。

如果你熟悉其它的 MVC Web开发框架,比方说 Ruby on Rails,你可能会认为 Django 视图是控制器,而 Django 模板是视图。 很不幸,这是对 MVC 不同诠释所引起的错误认识。 在 Django 对 MVC 的诠释中,视图用来描述要展现给用户的数据;不是数据 如何展现 ,而且展现 哪些 数据。 相比之下,Ruby on Rails 及一些同类框架提倡控制器负责决定向用户展现哪些数据,而视图则仅决定 如何 展现数据,而不是展现 哪些 数据。

Django框架简介_第4张图片

MTV的响应模式如下所示:

  1. Web服务器(中间件)收到一个http请求
  2. Django在URLconf里查找对应的视图(View)函数来处理http请求
  3. 视图函数调用相应的数据模型来存取数据、调用相应的模板向用户展示页面
  4. 视图函数处理结束后返回一个http的响应给Web服务器
  5. Web服务器将响应发送给客户端

Django中的配置文件的简介

url.py详解

Django 决定要使用的根URLconf 模块。通常,这个值就是ROOT_URLCONF 的设置,但是如果进来的HttpRequest 对象具有一个urlconf 属性(通过中间件request processing 设置),则使用这个值来替换ROOT_URLCONF 设置。

url.py:URL分发器(路由配置文件)
URL配置(URLconf)就像配置Django所支持的网站目录,他的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表。

URL模式:

urlpatterns = [
       url(正则表达式,view函数,参数,别名,前缀),
]

#url的函数定义
url(regex, view, kwargs=None, name=None):
实例:正则表达式的匹配

下面是一个简单的 URLconf:

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 中捕获一个值,只需要在它周围放置一对圆括号。
  • 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
  • 每个正则表达式前面的’r’ 是可选的但是建议加上。它告诉Python 这个字符串是“原始的” —— 字符串中任何字符都不应该转义。

一些请求的例子:

  1. /articles/2005/03/ 请求将匹配列表中的第三个模式。Django
    将调用函数views.month_archive(request, ‘2005’, ‘03’)。
  2. /articles/2005/3/ 不匹配任何URL 模式,因为列表中的第三个模式要求月份应该是两个数字。
  3. /articles/2003/
    将匹配列表中的第一个模式不是第二个,因为模式按顺序匹配,第一个会首先测试是否匹配。请像这样自由插入一些特殊的情况来探测匹配的次序。
  4. /articles/2003 不匹配任何一个模式,因为每个模式要求URL 以一个斜线结尾。
  5. /articles/2003/03/03/ 将匹配最后一个模式。Django 将调用函数views.article_detail(request, ‘2003’, ‘03’, ‘03’)。
正则表达中传递参数(命名组)

上面的示例使用简单的、没有命名的正则表达式组(通过圆括号)来捕获URL 中的值并以位置 参数传递给视图。在更高级的用法中,可以使用命名的正则表达式组来捕获URL 中的值并以关键字 参数传递给视图。

在Python 正则表达式中,命名正则表达式组的语法是(?Ppattern),其中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[0-9]{4})/$', views.year_archive),
    url(r'^articles/(?P[0-9]{4})/(?P[0-9]{2})/$', views.month_archive),
    url(r'^articles/(?P[0-9]{4})/(?P[0-9]{2})/(?P[0-9]{2})/$', views.article_detail),
]

这个实现与前面的示例完全相同,只有一个细微的差别:捕获的值作为关键字参数而不是位置参数传递给视图函数。例如:

  1. /articles/2005/03/ 请求将调用views.month_archive(request, year=’2005’, month=’03’)函数,而不是views.month_archive(request, ‘2005’, ‘03’)。
  2. /articles/2003/03/03/ 请求将调用函数views.article_detail(request, year=’2003’, month=’03’, day=’03’)。

在实际应用中,这意味你的URLconf 会更加明晰且不容易产生参数顺序问题的错误 —— 你可以在你的视图函数定义中重新安排参数的顺序。当然,这些好处是以简洁为代价;conf

命名组和传递参数的区别:
该方法传递的参数是变量,可以根据客户端等的不同而变化,但是使用ru()中传递的参数是固定值。

实例:传递参数

urls.py

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

'''向views中的hello函数中传递参数a'''
urlpatterns = [
       url(r'^hello/$', views.hello,{'a':123}),
]

views.py

from django.shortcuts import render
from django.contrib.auth.models import User
# Create your views here.


'''函数hello接收参数a,否则会报错'''
def hello(request,a):
    user_list = User.objects.all()
    print(a)
    return  render(request,"table.html ",{'user_list':user_list})

URL的分解器,include函数

通常一个URL分解器对应一个URL匹配模块,它可以包含多个URL模式,也可以包含多个其他的URL分解器。通常这种包含关系结构设计,实现了Django对URL的层级解析。

工程中的urls.py配置

''' 包含app中URL的配置文件
    1.导入incloude():
        from django.conf.urls import url, include
    2. 增加URL的参数:  
        url(r'^blog/', include('blog.urls'))
        r'^blog/' :访问的后缀
        include('blog.urls'):指定包含的URL的存放位置。blog目录下的urls模块
'''
from django.conf.urls import url,include
from django.contrib import admin


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include('hello.urls')),
]

app中的urls.py的配置

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


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

注意:访问URL时,URL是项目中URL中配置加app中的URL。如果在工程中的URl中设置url(r'^abc/', include('hello.urls')),在app中设置url(r'^hello/$', views.hello),访问时输入的URl为http://127.0.0.1:8000/abc/hello/

总结

urls.py中,需要配置访问时的URL

  1. 设置urls.py的主目录

    '''在工程目录中的seting.py中设置,设置工程mysite下的urls为主URL的配置文件'''
    ROOT_URLCONF = 'mysite.urls'
  2. 配置方法:

    '''配置URL的正则表达式以及对应的URL对应的操作(函数)'''
    from django.conf.urls import url
    urlpatterns = [
           url('正则表达式', '操作函数''参数','别名','前缀'),
    ]
    
  3. 为方便管理URL设置层目录include函数

    ''' 包含app中URL的配置文件
    1.导入incloude():
        from django.conf.urls import url, include
    2. 增加URL的参数:  
        url(r'^blog/', include('blog.urls'))
        r'^blog/' :访问的后缀
        include('blog.urls'):指定包含的URL的存放位置。blog目录下的urls模块
    '''
    from django.conf.urls import url,include
    from django.contrib import admin
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^', include('hello.urls')),
    ]

view.py简介

Django 使用Request 对象和Response 对象在系统间传递状态。

当请求一个页面时,Django会建立一个包含请求元数据的 HttpRequest 对象。 当Django 加载对应的视图时,HttpRequest 对象将作为视图函数的第一个参数。每个视图会返回一个HttpResponse 对象。

from django.shortcuts import render
from django.contrib.auth.models import User

from django.http import HttpRequest,HttpResponse

def hello(request,a):
    user_list = User.objects.all()
    print(a)
    return  render(request,"table.html ",{'user_list':user_list})

HttpRequest对象

在函数最开始的第一个参数,request是HttpRequest的实例。

属性
  • HttpRequest.scheme

    一个字符串,表示请求的方案(通常是http 或https)

  • HttpRequest.body

    一个字节字符串,表示原始HTTP 请求的正文。它对于处理非HTML 形式的数据非常有用:二进制图像、XML等。 如果要处理常规的表单数据,应该使用HttpRequest.POST。

  • HttpRequest.path

    一个字符串,表示请求的页面的完整路径,不包含域名。例如:”/music/bands/the_beatles/”

  • HttpRequest.method

    一个字符串,表示请求使用的HTTP 方法。必须使用大写

    if request.method == 'GET':
        do_something()
    elif request.method == 'POST':
        do_something_else()
  • HttpRequest.GET

    一个类似于字典的对象,包含HTTP GET 的所有参数

  • HttpRequest.POST

    一个包含所有给定的HTTP POST参数的类字典对象,提供了包含表单数据的请求。详情请参考下面的QueryDict 文档。如果需要访问请求中的原始或非表单数据,可以使用HttpRequest.body 属性。

    POST 请求可以带有空的POST 字典 —— 如果通过HTTP POST 方法请求一个表单但是没有包含表单数据的话。因此,不应该使用if request.POST 来检查使用的是否是POST 方法;应该使用if request.method == “POST”(参见上文)。|

    注意:POST 不包含上传的文件信息

  • HttpRequest.COOKIES

    一个标准的Python 字典,包含所有的cookie。键和值都为字符串

  • HttpRequest.FILES

    一个类似于字典的对象,包含所有的上传文件。FILES 中的每个键为 中的name。

    注意,FILES 只有在请求的方法为POST 且提交的 带有enctype=”multipart/form-data” 的情况下才会包含数据。否则,FILES 将为一个空的类似于字典的对象

  • HttpRequest.META

    一个标准的Python 字典,包含所有的HTTP 头部。具体的头部信息取决于客户端和服务器,下面是一些示例:

    CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。
    CONTENT_TYPE —— 请求的正文的MIME 类型。
    HTTP_ACCEPT —— 响应可接收的Content-Type。
    HTTP_ACCEPT_ENCODING —— 响应可接收的编码。
    HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。
    HTTP_HOST —— 客服端发送的HTTP Host 头部。
    HTTP_REFERER —— Referring 页面。
    HTTP_USER_AGENT —— 客户端的user-agent 字符串。
    QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。
    REMOTE_ADDR —— 客户端的IP 地址。
    REMOTE_HOST —— 客户端的主机名。
    REMOTE_USER —— 服务器认证后的用户。
    REQUEST_METHOD —— 一个字符串,例如”GET” 或”POST”。
    SERVER_NAME —— 服务器的主机名。
    SERVER_PORT —— 服务器的端口(是一个字符串)。
    从上面可以看到,除CONTENT_LENGTH 和CONTENT_TYPE 之外,请求中的任何HTTP 头部转换为META 的键时,都会将所有字母大写并将连接符替换为下划线最后加上HTTP_ 前缀。所以,一个叫做X-Bender 的头部将转换成META 中的HTTP_X_BENDER 键。

  • HttpRequest.user

    一个AUTH_USER_MODEL 类型的对象,表示当前登录的用户。如果用户当前没有登录,user 将设置为django.contrib.auth.models.AnonymousUser 的一个实例。你可以通过is_authenticated() 区分它们,像这样:

    if request.user.is_authenticated():
        # Do something for logged-in users.
    else:
        # Do something for anonymous users.

    user 只有当Django 启用AuthenticationMiddleware 中间件时才可用。更多信息,参见Django 中的用户认证。

  • HttpRequest.session

    一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用

Response对象

每一个view请求处理方法必须有一个HttpResponse对象的

传递字符串

典型的应用是传递一个字符串作为页面的内容到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 看做一个类文件对象

>>> response = HttpResponse()
>>> response.write("

Here's the text of the Web page.

"
) >>> response.write("

Here's another paragraph.

"
)
Django的快捷函数
render

格式:

render(request, template_name[, context][, context_instance][, content_type][, status][, current_app][, dirs][, using])[source]
结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象

必选参数:
request:该request用于生成response
template_name:要使用的模板的完整名称或者模板名称的一个序列。

可选参数:
content_type:生成的文档要使用的MIME 类型。默认为DEFAULT_CONTENT_TYPE 设置的值
status:响应的状态码。默认为200

下面的示例渲染模板myapp/index.html,MIME 类型为application/xhtml+xml:

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 RequestContext, loader

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

格式:

render_to_response(template_name[, context][, context_instance][, content_type][, status][, dirs][, using])[source]

根据一个给定的上下文字典渲染一个给定的目标,并返回渲染后的HttpResponse

必选参数:
template_name:要使用的模板的完整名称或者模板名称的一个序列。如果给出的是一个序列,将使用存在的第一个模板。

可选参数:
content_type:生成的文档要使用的MIME 类型。默认为DEFAULT_CONTENT_TYPE 设置的值
status:响应的状态码。默认为200

实例:

下面的示例渲染模板myapp/index.html,MIIME 类型为application/xhtml+xml:

from django.shortcuts import render_to_response

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

这个示例等同于:

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

def my_view(request):
    # View code here...
    t = loader.get_template('myapp/index.html')
    c = Context({'foo': 'bar'})
    return HttpResponse(t.render(c),
        content_type="application/xhtml+xml")
重定向
redirect(to, [permanent=False, ]*args, **kwargs)[source]

为传递进来的参数返回HttpResponseRedirect 给正确的URL 。

参数可以是:

  • 一个模型:将调用模型的get_absolute_url() 函数
  • 一个视图,可以带有参数:将使用urlresolvers.reverse 来反向解析名称
  • 一个绝对的或相对的URL,将原封不动的作为重定向的位置。

默认返回一个临时的重定向;传递permanent=True 可以返回一个永久的重定向

示例:

  1. 通过传递一个对象;将调用get_absolute_url() 方法来获取重定向的URL:

    from django.shortcuts import redirect
    
    def my_view(request):
        ...
        object = MyModel.objects.get(...)
        return redirect(object)
  2. 通过传递一个视图的名称,可以带有位置参数和关键字参数;将使用reverse() 方法反向解析URL:

    def my_view(request):
        ...
        return redirect('some-view-name', foo='bar')
  3. 传递要重定向的一个硬编码的URL:

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

    也可以是一个完整的URL:

    def my_view(request):
        ...
        return redirect('http://example.com/')

    默认情况下,redirect() 返回一个临时重定向。以上所有的形式都接收一个permanent 参数;如果设置为True,将返回一个永久的重定向:

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

Django包含了一系列的HttpResponse衍生类(子类),用来处理不同类型的HTTP 响应(response)。与 HttpResponse相同, 这些衍生类(子类)存在于django.http之中。

  • class HttpResponseRedirect

    构造函数的第一个参数是必要的 — 用来重定向的地址。这些能够是完全特定的URL地址(比如,’http://www.yahoo.com/search/‘),或者是一个不包含域名的绝对路径地址(例如, ‘/search/’)。关于构造函数的其他参数,可以参见 HttpResponse。注意!这个响应会返回一个302的HTTP状态码。

    url
    这个只读属性,代表响应将会重定向的URL地址(相当于Location response hader)。

  • class HttpResponsePermanentRedirect
    与HttpResponseRedirect一样,但是它会返回一个永久的重定向(HTTP状态码301)而不是一个“found”重定向(状态码302)。

  • class HttpResponseNotModified
    构造函数不会有任何的参数,并且不应该向这个响应(response)中加入内容(content)。使用此选项可指定自用户上次请求(状态代码304)以来尚未修改页面。

  • class HttpResponseBadRequest
    与HttpResponse的行为类似,但是使用了一个400的状态码。

  • class HttpResponseNotFound
    与HttpResponse的行为类似,但是使用的404状态码。

  • class HttpResponseForbidden
    与HttpResponse类似,但使用403状态代码。

数据库

在项目的目录下setings.py中

#setings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

mysql:
引擎的名称:django.db.backends.mysql

mysql的驱动程序:

  • MySQLdb是一个由Andy Dustman开发,已经发展并支持十多年的一个本地驱动。
  • mysqlclient是MySQLdb的一个分支,它与python3有着特别好的契合并且可以作为MySQLdb的直接替代。在书写这篇的时候,这是在Django使用MySQL的推荐的选择。
  • MySQL Connector/Python是一个来自Oracle的纯python驱动,它不需要MySQL client库或在标准库之外的任何Python模块。
  • PyMySQL(纯python的mysql驱动):

连接数据库

  • 安装PyMySQL
  • 修改配置文件
  • 在工程目录中init.py中写入:

    import pymysql
    pymysql.install_as_MySQLdb()

连接设置将被用在这些命令上:

  • OPTIONS
  • NAME,USER,PASSWORD,HOST,PORT
  • MySQL选项文件。

换句话说,如果你设置数据库的名称在OPTIONS, 这将优先于NAME, 这将覆盖任何在MySQL option file中的东西.

下面是使用一个MySQL选择文件一个示例配置:

# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'OPTIONS': {
            'read_default_file': '/path/to/my.cnf',
        },
    }
}


# my.cnf
[client]
database = NAME
user = USER
password = PASSWORD
default-character-set = utf8

其他几个MySQLdb连接选项可能是有用的,例如ssl, init_command, and sql_mode. 查阅 MySQLdb documentation了解更多细节。

初始化数据库

> python manage.py migrate

ORM机制简介

ORM是什么?:(在django中,根据代码中的类自动生成数据库的表也叫–code first)

ORM:Object Relational Mapping(对象关系映射)

类名对应——》数据库中的表名

类属性对应———》数据库里的字段

类实例对应———》数据库表里的一行数据

obj.id obj.name…..类实例对象的属性

调用sql语句

# views.py

from django.shortcuts import render
from django.contrib.auth.models import User

from django.http import HttpRequest,HttpResponse

# Create your views here.
def hello(request,a):
    user_list = User.objects.all()
    print(user_list.query)
    return  render(request,"table.html ",{'user_list':user_list})

直接在屏幕上显示执行的sql语句

# 在project的setings.py

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

常用操作

'''准备环境'''
D:\pythonwork\django\mysite>python manage.py shell
>>> from hello.models import *
插入数据

create和save方法

objects:model默认管理器,create是管理器的方法,save是model对象的方法。
插入主外键关系的时候,可以用对象的方式,也可以直接关联ID的方式
插入多对多关系的时候要分步操作。

插入一个作者:

'''创建一个作者'''
>>> Author.objects.create(name='tom')
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
(0.052) INSERT INTO `hello_author` (`name`) VALUES ('tom'); args=['tom']

>>>

插入一个作者的详细记录:

>>> AuthorDetail.objects.create(sex=0,email='[email protected]',address='北京市海淀区梧桐路25号',birthday='19920202',author_id=1)

插入一个出版社的记录

>>> pub = Publisher()
>>> pub.name = "中国电子出版社"
>>> pub.address = "北京市"
>>> pub.city = "北京市"
>>> pub.state_province = '北京市'
>>> pub.country = '中国'
>>> pub.website = 'http://www.miner-k.com'
>>> pub.save()
(0.052) INSERT INTO `hello_publisher` (`name`, `address`, `city`, `state_provinc
e`, `country`, `website`) VALUES ('中国电子出版社', '北京市', '北京市', '北京市'
, '中国', 'http://www.miner-k.com'); args=['中国电子出版社', '北京市', '北京市',
 '北京市', '中国', 'http://www.miner-k.com']

插入一本书的记录

>>> Book.objects.create(title='python入门到精通',publisher=pub,publisher_date='2012-12-12')
(0.067) INSERT INTO `hello_book` (`title`, `publisher_id`, `publisher_date`) VALUES ('python入门到精通', 1, '2012-12-12'); args=['python入门到精通', 1, '2012-12-12']

插入书、作者、出版商关系的记录

>>> book = Book.objects.get(id=1)
(0.002) SELECT VERSION(); args=None
(0.002) SELECT `hello_book`.`id`, `hello_book`.`title`, `hello_book`.`publisher_id`, `hello_book`.`publisher_date` FROM `hello_book` WHERE `hello_book`.`id` = 1; args=(1,)

>>> author = Author.objects.get(id=1)
(0.002) SELECT `hello_author`.`id`, `hello_author`.`name` FROM `hello_author` WHERE `hello_author`.`id` = 1; args=(1,)

>>> book.authors.add(author)
(0.004) SELECT `hello_book_authors`.`author_id` FROM `hello_book_authors` WHERE
(`hello_book_authors`.`book_id` = 1 AND `hello_book_authors`.`author_id` IN (1)); args=(1, 1)
(0.066) INSERT INTO `hello_book_authors` (`book_id`, `author_id`) VALUES (1, 1); args=(1, 1)
>>>
修改数据

update和save方法
updete是QuerySet对象的方法

>>> author = Author.objects.get(id=1)
(0.002) SELECT `hello_author`.`id`, `hello_author`.`name` FROM `hello_author` WHERE `hello_author`.`id` = 1; args=(1,)
>>> author.name = 'jim'
>>> author.save()
(0.586) UPDATE `hello_author` SET `name` = 'jim' WHERE `hello_author`.`id` = 1;args=('jim', 1)
查询数据(惰性查询)

所谓的惰性查询:publisher.objects.all()只是返回一个QuarySet(查询结果集对象),并不会马上执行sql,而是当调用QuerySet的时候才会执行。

>>> Author.objects.all()
(0.002) SELECT `hello_author`.`id`, `hello_author`.`name` FROM `hello_author` LIMIT 21; args=()
]>

>>> Book.objects.all()
(0.002) SELECT `hello_book`.`id`, `hello_book`.`title`, `hello_book`.`publisher_id`, `hello_book`.`publisher_date` FROM `hello_book` LIMIT 21; args=()
]>
删除

delete方法

删除id为1的书籍

'''删除指定id的书籍'''

>>> Book.objects.filter(id=1).delete()
(0.003) SELECT `hello_book`.`id`, `hello_book`.`title`, `hello_book`.`publisher_
id`, `hello_book`.`publisher_date` FROM `hello_book` WHERE `hello_book`.`id` = 1; args=(1,)
(0.069) DELETE FROM `hello_book_authors` WHERE `hello_book_authors`.`book_id` IN (1); args=(1,)
(0.001) DELETE FROM `hello_book` WHERE `hello_book`.`id` IN (1); args=(1,)
(2, {'hello.Book': 1, 'hello.Book_authors': 1})
QuerySet常用的查询相关的API

执行查询的相关链接
QuerySet特点:
1.可迭代的
2.可切片的

# python manage.py shell
'''将查询的结果存储到一个变量中,通过查看变量的类型发现返回值是QuerySet类。 '''
>>> from hello.models import *
>>> pub_list = Publisher.objects.all()
>>> type(pub_list)
<class 'django.db.models.query.QuerySet'>

>>> for pub in pub_list:
...  print(pub.name)
...

中国电子出版社
通过get获取一个单一的对象

filter() 始终给你一个查询集,即使只有一个对象满足查询条件 —— 这种情况下,查询集将只包含一个元素。

如果你知道只有一个对象满足你的查询,你可以使用管理器的get() 方法,它直接返回该对象:

通过all获取所有的对象

获取一个表中所有对象的最简单的方式是全部获取。可以使用管理器的all() 方法:

>>> pub_list = Publisher.objects.all()

all()方法返回包含数据库中所有对象的一个查询集。

通过过滤器获取特定的对象

all()方法 返回了一个包含数据库表中所有记录查询集 。但在通常情况下,你往往想要获取的是完整数据集的一个子集。

要创建这样一个子集,你需要在原始的的查询集上增加一些过滤条件。两个最普遍的途径是:

filter(**kwargs)
返回一个新的查询集 ,它包含满足查询参数的对象。
exclude(**kwargs)
返回一个新的查询集 ,它包含不满足查询参数的对象。
查询参数(上面函数定义中的**kwargs)需要满足特定的格式,下面字段查询一节中会提到。

举个例子,要获取年份为2006的所有文章的查询集,可以使用filter()方法:

>>> Author_list = Author.objects.filter(id=1)
返回第一个、最后一条结果

first()
返回结果集的第一个对象, 当没有找到时返回None.如果 QuerySet 没有设置排序,则将会自动按主键进行排序
例:

>>> Author.objects.all()
>>> Author.objects.all().first()

last()
工作方式类似first(),只是返回的是查询集中最后一个对象。

显示指定字段的值

values(*fields)
返回一个ValuesQuerySet —— QuerySet 的一个子类,迭代时返回字典而不是模型实例对象。而是一个可迭代的字典序列。

values_list
它与values()非常相似,只不过后者返回的结果是字典序列,而values_list()返回的是元组序列。

>>> Book.objects.filter(id=1).values('title','publisher_date')

'title': '岩石力学', 'publisher_date': datetime.date(2017, 11, 7)}]>


>>> Book.objects.filter(id=1).values_list('title','publisher_date')

'岩石力学', datetime.date(2017, 11, 7))]>
QuerySet API参考
实例(单表查询)
  • 查询id为1的书籍,并只显示数据名称和出版日期

    >>> Book.objects.filter(id=1).values('title','publisher_date')
    'title': '岩石力学', 'publisher_date': datetime.date(2017, 11, 7)}]>
    >>> Book.objects.filter(id=1).values_list('title','publisher_date')
    '岩石力学', datetime.date(2017, 11, 7))]>
  • 查询所有的出版社信息,并按照id降序排列,并尝试使用reverse方法进行反向排序。

    >>> Publisher.objects.all().order_by('id').values('name')
    'name': '中国电子出版社'}, {'name': '中国工业出版社'}, {'name': '山
    西教育出版社'}]>
    >>> Publisher.objects.all().order_by('-id').values('name')
    'name': '山西教育出版社'}, {'name': '中国工业出版社'}, {'name': '中
    国电子出版社'}]>
    >>> Publisher.objects.all().order_by('id').values('name').reverse()
    'name': '山西教育出版社'}, {'name': '中国工业出版社'}, {'name': '中
    国电子出版社'}]>
  • 显示所有的出版社的地址,不能重复

    >>> Publisher.objects.all().values('city')
    'city': '北京市'}, {'city': '天津市'}, {'city': '太原市'}, {'city':
    '太原市'}, {'city': '北京市'}, {'city': '北京市'}]>
    
    >>> Publisher.objects.all().values('city').distinct()
    
    'city': '北京市'}, {'city': '天津市'}, {'city': '太原市'}]>
  • 查询北京市的出版社

    >>> Publisher.objects.filter(city='北京市').values('name')
    (0.002) SELECT `hello_publisher`.`name` FROM `hello_publisher` WHERE `hello_publ
    isher`.`city` = '北京市' LIMIT 21; args=('北京市',)
    <QuerySet [{'name': '中国电子出版社'}, {'name': '清华大学出版社'}, {'name': '北
    大教育出版社'}]>
  • 查询北京市除外的出版社

    >>> Publisher.objects.exclude(city='北京市').values('name')
    
    'name': '中国工业出版社'}, {'name': '山西教育出版社'}, {'name': '山
    西大学出版社'}]>
  • 查询男作者的数量

    >>> AuthorDetail.objects.filter(sex='男').count()
    (0.638) SELECT COUNT(*) AS `__count` FROM hello_authordetail` WHERE `hello_auth ordetail`.`sex` = '男'; args=('男',)
    3
实例(多表查询)

多表查询的技巧:
__ : 两个下划线可以生成连接查询,查询关联的字段信息
_set:提供了对象访问相关联表数据的方法,但是这种方式只能是相关类访问定义了关系的类(主键类访问外键类)

Publisher 类是Book类的主键类,

'''此处获取Publisher对象只能通过get方法获取,不能使用filter()'''

>>> pub_list = Publisher.objects.get(name='中国工业出版社')

>>> pub_list.book_set.all()
]>

>>> pub_list.book_set.all().values('title')
'title': '流体力学'}]>
  • 查询客户的完整信息

    '''AuthorDetail中的属性author是与表Author关联,如果直接打印author属性,打印的是author_id.如果需要打印Author的属性name,需要打印变量author__name'''
    
    >>> from hello.models import *
    >>> AuthorDetail.objects.values('sex','email','address','birthday','author')
    
    'address': '北京市海淀区梧桐路25号', 'birthday': '19920202', 'author': 1, 'sex': '男', 'email': '[email protected]'}, {'address': '上海市外滩32号', 'bir
    thday': '19921201', 'author': 2, 'sex': '男', 'email': '[email protected]'}, {'address': '广州市广陵大道21号', 'birthday': '19981232', 'author': 3, 'sex': '女', 'email': '[email protected]'}, {'address': '深圳市为民道11号', 'birthday': '19990303', 'author': 4, 'sex': '男', 'email': '[email protected]'}]>
    
    >>> AuthorDetail.objects.values('sex','email','address','birthday','author__name')
    
    'address': '北京市海淀区梧桐路25号', 'birthday': '19920202', 'author__name': 'jim', 'sex': '男', 'email': '[email protected]'}, {'address': '上海市外滩32号', 'birthday': '19921201', 'author__name': 'jim', 'sex': '男', 'email': '[email protected]'}, {'address': '广州市广陵大道21号', 'birthday': '19981232', 'author__name': 'lucy', 'sex': '女', 'email': '[email protected]'}, {'address': '深圳市为民道11号', 'birthday': '19990303', 'author__name': 'jick', 'sex': '男', 'email': '[email protected]'}]>
  • 查询一本数书的作者姓名、出版社的名字

    >>> Book.objects.filter(title='岩石力学').values('title','authors','publisher')
    
    'publisher': 1, 'authors': 1, 'title': '岩石力学'}]>
    
    >>> Book.objects.filter(title='岩石力学').values('title','authors__name','publisher__name')
    
    'publisher__name': '中国电子出版社', 'title': '岩石力学', 'authors__name': 'jim'}]>
  • 查询一个作者写的所有的书籍

    >>> Book.objects.filter(authors__name='jim').values('title')
    
    'title': '岩石力学'}]>
实例(聚合和分组查询)

聚合查询
aggrate通过QuerySet进行计算,返回一个聚合值的字典,aggregate()每一个参数都指定一个包含在字典中的返回值。

  • 查询某一个出版社出版书的数量

    利用QuerySet的API

    >>> from hello.models import *
    >>> Publisher.objects.filter(name='中国工业出版社').count()
    1
    

    利用聚合查询aggregate

    '''导入涉及到的模块'''
    >>> from django.db.models import *
    >>> Publisher.objects.filter(name='中国工业出版社').aggregate(Count('name'))
    
    {'name__count': 1}
  • 查询某一个作者出版书籍的总价

    >>> Book.objects.filter(authors__name='jim').aggregate(Sum('price'))
    
    {'price__sum': Decimal('10.00')}

分组查询annotate

可以为QuerySet中的每一个对象添加注解,可以通过计算机查询的结果中的每一个对象所关联的对象集合,从而得出总计价(也可是平均值或总和等)

  • 查询所有的作者对应的所有出书的价格

    >>> Book.objects.values('authors__name').annotate(Sum('price'))
    
    <QuerySet [{'authors__name': 'jim', 'price__sum': Decimal('10.00')}, {'authors__
    name': 'lucy', 'price__sum': Decimal('10.00')}, {'authors__name': 'jick', 'price
    __sum': Decimal('10.00')}]>
  • 查询所有出版社最便宜书籍的价格

    >>> Book.objects.values('publisher__name').annotate(Min('price'))
    
    <QuerySet [{'price__min': Decimal('10.00'), 'publisher__name': '中国电子出版社'}
    , {'price__min': Decimal('10.00'), 'publisher__name': '中国工业出版社'}, {'price
    __min': Decimal('10.00'), 'publisher__name': '山西教育出版社'}]>

数据模型

一对一:

作者模型:一个作者有姓名(一对一)
作者详情模型:作者的详情中有,性别、email地址、和出生日期、作者详情模型和作者模型之间是一对一的关系

一对多:

出版商模型:出版商有名称、地址、所在城市、省、国家、网站。
书籍模型:书籍有书名和出版商。一本书可以有多个作者,一个作者可以有多本书,所以作者和书籍的关系是多对多的关系【many-to-many】。一本书只能是一个出版商出版,一个出版商可以出版多本书,出版商和书籍是一对多的关系【one-to-many】,也被称为外键【foreignkey】

修改配置文件


# models.py

from django.db import models

# Create your models here.
class Publisher(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()


class Author(models.Model):
    name = models.CharField(max_length=30)


class AuthorDetail(models.Model):
    sex = models.CharField(max_length=1,choices=((0,'男'),(1,'女')))
    email = models.CharField()
    address = models.CharField(max_length=50)
    birthday = models.CharField()
    author = models.OneToOneField(Author)

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publisher_date = models.DateField()

代码简介:

  • 每个数据模型类型都是Django.db.models.Models的子类。它的的父类Model中包含了所有必要的和数据库交互的方法,并提供了一个简洁漂亮的定义数据库字段的语法。
  • 每个模型相当于单个数据库表(这条规则的例外情况是多对多的关系,多对多关系的时候会多生出一张表关系),每个属性也是这个表的一个字段,属性名是字段名,它的类型(例如CharField)相当于数据库的字段类型(例如varchar)。
  • 模型之间的关系:一对一(OneToOneField),一对多(ForeignKey)和多对多(ManyToManyField)

生成数据库同步脚本

> python manage.py makemigrations

同步数据库

> python manage.py migrate

查看数据库的变化

同步数据库之前:

Django框架简介_第5张图片

同步数据库之后:

Django框架简介_第6张图片

新增加的表就是在models.py中的class。表名就是库名,表中的字段就是类的属性。

常用的字段类型:

字段类型 含义
AutoField 一个根据实际ID自动增长的IntegerField
BigIntegerField 一个64位整数, 类似于一个 IntegerField
BinaryField 二进制类型
BooleanField 布尔字段类型
CharField 字符串类型
DateField 日期字段
DateTimeField 日期时间字段
DecimalField 精确小数字段
EmailField email字段类型
FileField 文件字段类型
FloatField 浮点数字段类型
ImageField 图片字段类型
IntegerField 整数字段类型
IPAddressField IP字段类型
SmallIntegerField 小整型字段类型
TextField 文本字段类型
URLField url字段类型

更多类型类型链接

字段选项

字段选项名称 含义
null 如果为True,Django将在数据库中将空值存储为NULL。默认值是 False
blank 如果为True,则该字段允许为空白。 默认值是 False
choices 它是一个可迭代的结构(比如,列表或是元组),由可迭代的二元组组成(比如[(A, B), (A, B) …]),用来给这个字段提供选择项。
default 该字段的默认值
help_text 额外的 ‘help’ 文本将被显示在表单控件form中
primary_key 若为 True, 则该字段会成为模型的主键字段
unique 如果为 True, 这个字段在表中必须有唯一值

参考文档

数据库同步

'''如果数据库中字段增加或修改,需啊哟重新同步数据库'''
D:\pythonwork\django\mysite>python manage.py makemigrations

You are trying to add a non-nullable field 'price' to book without a default; we
 can''t do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows with a null
value for this column)
'''第二点中提示退出设置增加字段的默认值,在增加的字段中添加参数default='''
 2) Quit, and let me add a default in models.py
Select an option: 2

D:\pythonwork\django\mysite>python35 manage.py makemigration

D:\pythonwork\django\mysite>python35 manage.py migrate

认识一个目录

目录名:migrations
作用:用来存放通过makemirgrations命令生成的数据库脚本。app目录下面必须要有migrations的目录且该目录下必须存放__init__.py才能正常的使用数据库的同步功能。

认识一张表(django_migrations)

记录migrantions目录下脚本的使用情况

和数据库相关的命令

flush:清空数据库,恢复数据库到最初的状态
makemigrantions:生成数据同步的脚本
migrate:同步数据库
showmigrations:查看生成的数据库同步脚本
sqlflush:查看生成清空数据库的脚本
sqlmigrate:查看数据库同步的sql语句

使用原生的sql

使用原生sql的方式主要的目的是解决一些复杂的sql不能用ORM的方式写出的问题。

extra:结果集修改器,一种提供额外查询参数的机制
raw:执行原始sql并返回模式实例
直接自定义SQL(这种方式不依赖于model,前两种方式要依赖于model)

extra实例

  • 查询山西教育出版社出版所有价格大于10元的图书

    >>> Book.objects.filter(publisher__name='山西教育出版社').extra(where=['price>10']).values('title')
    
    'title': '材料力学'}, {'title': '工程力学'}]>

    等价于

    >>> Book.objects.filter(publisher__name='山西教育出版社',price__gt=10).values('title')
    
    'title': '材料力学'}, {'title': '工程力学'}]>

使用raw

>>> Book.objects.raw('select * from hello_book')

>>> book_list = Book.objects.raw('select * from hello_book')
>>> for book in book_list:
...   print(book.title)
...
(0.003) select * from hello_book; args=()
岩石力学
流体力学
材料力学
工程力学

使用自定sql语句

>>> from django.db import connection
>>> cursor = connection.cursor()

'''插入数据'''
>>> cursor.execute('insert into hello_author(name) values("郭敬明")')
(0.087) insert into hello_author(name) values("郭敬明"); args=None
1

'''修改数据'''
>>> cursor.execute('update hello_author set name="韩寒" where name="郭敬明"')
(0.071) update hello_author set name="韩寒" where name="郭敬明"; args=None
1

'''删除数据'''
>>> cursor.execute('delete from hello_author where name="韩寒"')
(0.205) delete from hello_author where name="韩寒"; args=None
1

'''查询语句'''
>>> cursor.execute('select * from hello_author')
(0.002) select * from hello_author; args=None
4

'''获取数据'''
>>> raw = cursor.fetchone()
>>> cursor.fetchone()
(2, 'jim')
>>> cursor.fetchone()
(3, 'lucy')
>>> cursor.fetchone()
(4, 'jick')
>>> cursor.fetchone()

模板

常用标签

autoescape控制自动转义

控制自动转义是否可用.这种标签带有任何 on 或 off 作为参数的话,他将决定转义块内效果。该标签会以一个endautoescape作为结束标签.

当自动转义生效时,所有变量内容会被转义成HTML输出(在所有过滤器生效后)这等同与手动将escape筛选器应用于每个变量。

唯一一个例外是,变量或者通过渲染变量的代码,或者因为它已经应用了 safe或escape过滤器,已经被标记为“safe”。

例如:
在views.py中

def test(request):
    value3 = "百度"
    return render(request,'test.html',locals())

在test.html中

{% autoescape on %}
    {{ values4 }}
{% endautoescape %}
if 标签的使用

格式:

{% if athlete_list %}
    Number of athletes: {{ athlete_list|length }}
{% elif athlete_in_locker_room_list %}
    Athletes should be out of the locker room soon!
{% else %}
    No athletes.
{% endif %}

实例:

#views.py

def test(request):
    number1 = 20
    return render(request,'test.html',locals())
#test.html


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test-Titletitle>
head>
<body>
{% if number1 == 10 %}
    NUM:10
{% elif number1 == 20 %}
    NUM:20
{% else %}
    unknow
{% endif %}
body>
html>
#mysite/urls.py

from django.conf.urls import url,include
from django.contrib import admin


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include('hello.urls')),
]
#hello/urls.py

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


urlpatterns = [
       url(r'^hello/$', views.hello,{'a':123}),
       url(r'^test/$', views.test),
]

访问测试:http://127.0.0.1:8000/test/

for标签的设置
#views.py

def test(request):
    number1 = 20
    num_list = [1,2,3,4,5,6,7,8]
    return render(request,'test.html',locals())
#test.html

<ul>
{% for num1 in num_list %}
    <li>{{ num1 }}li>
{% endfor %}
ul>

访问测试:http://127.0.0.1:8000/test/

verbatim标签

停止模板引擎在该标签的中渲染

{% verbatim %}
    {{if dying}}Still alive.{{/if}}
{% endverbatim %}
filter标签

将字符全部小写

{% filter force_escape|lower %}
    This text will be HTML-escaped, and will appear in all lowercase.
{% endfilter %}

全部转化为大写


{% filter force_escape|upper %}
    This text will be HTML-escaped, and will appear in all lowercase.
{% endfilter %}

内置过滤器

add

把add后的参数加给value

例如:

{{ value|add:"2" }}

如果 value 为 4,则会输出 6.

过滤器首先会强制把两个值转换成Int类型。如果强制转换失败, 它会试图使用各种方式吧两个值相加。它会使用一些数据类型 (字符串, 列表, 等等.) 其他类型则会失败. Day of the month, 2 digits with leading zeros.

例如:,我们使用下面的值

{{ first|add:second }}

first 是 [1, 2, 3] ,second 是 [4, 5, 6], 将会输出 [1, 2, 3, 4, 5, 6].

警告:

如果字符串可以被强制转换成int类型则会 summed,无法被转换,则和上面的第一个例子一样

addslashes在引号前面加上斜

例如,用于在CSV中转义字符串。

例如:
在views.py中

def test(request):
    number1 = 20
    num_list = [1,2,3,4,5,6,7,8]
    value = datetime.datetime.now()
    value1 = "I'm a boy"
    return render(request,'test.html',locals())

在test.html中

{{ value1|addslashes }}

如果value 是 “I’m using Django”, 输出将变成 “I\’m using Django”.

date

例如:

{{ value|date:"D d M Y" }}

如果value是datetime对象(例如,datetime.datetime.now()的结果),输出将是字符串 ‘Wed 09 Jan 2008’

default

如果value的计算结果为False,则使用给定的默认值。否则,使用该value。

例如:
在views.py中

def test(request):
    value2 = ""
    return render(request,'test.html',locals())

在test.html中

{{ value2|default:"nothing" }}

如果value为”“(空字符串),则输出将为nothing。

default_if_none

如果(且仅当)value为None,则使用给定的默认值。否则,使用该value。

注意,如果给出一个空字符串,默认值将不被使用。如果要回退空字符串,请使用default过滤器。

例如:

{{ value|default_if_none:"nothing" }}

如果value为None,则输出将为字符串“nothing”

escape 转义字符串

转义字符串的HTML。具体来说,它使这些替换:

<转换为<
>转换为>
'(单引号)转换为&#39;
"(双引号)转换为"
&转换为&

转义仅在字符串输出时应用,因此在连接的过滤器序列中escape的位置无关紧要:它将始终应用,就像它是最后一个过滤器。如果要立即应用转义,请使用force_escape过滤器。

将转义应用于通常会对结果应用自动转义的变量只会导致一轮转义完成。因此,即使在自动逃逸环境中使用此功能也是安全的。如果要应用多个转义通过,请使用force_escape过滤器。

例如,您可以在autoescape关闭时将escape应用于字段:

{% autoescape off %}
    {{ title|escape }}
{% endautoescape %}
filesizeformat 格式化文件大小

格式化数值为“人类可读”的文件大小(例如’13 KB’, ‘4.1 MB’, ‘102 bytes’等)。

例如:

{{ value|filesizeformat }}
first 返回列表中的第一个值

返回列表中的第一项。

例如:

{{ value|first }}
last 返回列表中的最后一个值

返回列表中的最后一个项目。

例如:

{{ value|last }}
safe 字符串不转义

将字符串标记为在输出之前不需要进一步的HTML转义。当自动转义关闭时,此过滤器不起作用。

注意:如果您要链接过滤器,在safe后应用的过滤器可能会使内容再次不安全。例如,以下代码按原样打印变量:

{{ var|safe|escape }}
truncatechars 截取指定个数的字符串

如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“…”)结尾。

参数:要截断的字符数

例如:

{{ value|truncatechars:5 }}

如果value是“Joel is a >,输出将为“Joel i …”。
如果value是”123456789”,输出结果为“12…”。输出的总共的字符串格式是5,包含三个省略号。

truncatewords 截取指定个数的单词

在一定数量的字后截断字符串。

参数:要截断的字数

例如:

{{ value|truncatewords:2 }}

如果value 是 “Joel is a slug”, 输出变为 “Joel is …”.

striptags

尽一切可能努力剥离所有[X] HTML标签。
例如:

{{ value|striptags }}

如果 value 的值是 “Joel is a slug“, 输出的结果是”Joel is a slug”.

无安全保证
请注意,striptags不会保证其输出是HTML安全的,尤其是对于无效的HTML输入。因此,NEVER将safe过滤器应用于striptags输出。如果您正在寻找更强大的功能,可以使用bleach Python库,特别是其clean方法。

模板的继承

include标签
  • 在模板的存放位置有sub.html和table.html两个模板

    在sub.html中

    
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
    head>
    <body>
    这是一个子模板
    body>
    html>

    table.html在body中增加下面一行

    ......
    <br> {% include 'sub.html' %}

    访问指定的页面会看到子模板中的内容。如果子模板在table.html同级目录下的dir1中,此处应该写
    {% include 'dir1\sub.html' %}

  • 传递变量到子模板中

    table.html在body中增加下面一行


    {% include "dir1/sub.html" with person="Jane" greeting="Hello" %}

    sub.html在body中增加变量

    <body>
    这是一个子模板{{person}}
    body>
block标签

views.py中增加

def test1(request):
     return render(request,'test1.html',locals())

在hello/urls.py中设置

urlpatterns = [
       url(r'^hello/$', views.hello,{'a':123}),
       url(r'^test/$', views.test),
       url(r'^testbase/$', views.test1),
]

base.html中


<html lang="en">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>{% block title %}我的基础模板{% endblock %}title>
head>

<body>
    <div id="sidebar">
        {% block sidebar %}
        <ul>
            <li><a href="/">Homea>li>
            <li><a href="/blog/">Bloga>li>
        ul>
        {% endblock %}
    div>

    <div id="content">
        {% block content %}{% endblock %}
    div>
body>
html>

test1.html中(base.html的子模板版)

{% extends "base.html" %}/span>

{% block title %}这是我的第I个子模板{% endblock %}

{% block content %}
这是子模板的内容
{% endblock %}

admin的后台管理

两种注册方法

注册方法

ModelAdmin objects
ModelAdmin类是模型在Admin 界面中的表示形式。通常,将它们在你的应用中的名为admin.py的文件里

from django.contrib import admin
from myproject.myapp.models import Author

class AuthorAdmin(admin.ModelAdmin):
    pass
admin.site.register(Author, AuthorAdmin)

如果对于默认的Admin 界面足够满意,那你根本不需要自己定义ModelAdmin 对象, 你可以直接注册模型类而无需提供ModelAdmin 的描述

from django.contrib import admin
from myproject.myapp.models import Author

admin.site.register(Author)

实例

在文件hello/admin.py中,

class PublisherAdmin(admin.ModelAdmin):
    list_display = ('name','address','city','state_province','country','website',)

admin.site.register(Author)
admin.site.register(Publisher,PublisherAdmin)
admin.site.register(AuthorDetail)
admin.site.register(Book)
注册装饰器
@admin.register(Publisher)
class PublisherAdmin(admin.ModelAdmin):
    list_display = ('name','address','city','state_province','country','website',)

admin.site.register(Author)
# admin.site.register(Publisher,PublisherAdmin)
admin.site.register(AuthorDetail)
admin.site.register(Book)

ModelAdmin 选项

list_display显示指定的字段

使用list_display 去控制哪些字段会显示在Admin 的修改列表页面中。

list_display = ('name','address','city','state_province','country','website',)
search_fields指定搜索的字段

这里写图片描述

search_fields = ('name','address')
list_filter指定列表过滤器

Django框架简介_第7张图片

list_filter = ('state_province',)
ordering排序
ordering = ('name',)

如果界面上有name字段,会在子段的旁边显示上下箭头(选择升序或者降序)

编辑表单 fields/exclude

只能编辑的表单

fields = ('name','address')

除了指定的字段之外的表单都能编辑

exclude = ('name','address')
fieldsets

界面显示:
Django框架简介_第8张图片

fieldsets = (
        (None, {
            'fields': ('name', 'address', )
        }),
        ('Advanced options', {
            'classes': ('collapse',),
            'fields': ('city', 'state_province', 'country')
        }),
    )

使用表单 form

django表单系统中,所有的表单类都是作为django.forms.form的子类创建的。包括ModelForm

关于表单系统主要分为两类,

基于django.forms.Form:所有表单类的父类
基于django.forms.ModelForm: 可以和模型类绑定的Form

不使用From的情况配置,添加出版社信息

/hello/urls.py

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


urlpatterns = [
       url(r'^hello/$', views.hello,{'a':123}),
       url(r'^test/$', views.test),
       url(r'^testbase/$', views.test1),
       url(r'^add_publisher/$', views.add_publisher,name='add_publisher'),

]

hello/views.py中增加函数


from hello.models import Publisher
.......

def add_publisher(request):
    if request.method == 'POST':
        # 如果是POST提交,去接受用户提交的数据
        name = request.POST.get('name')
        address = request.POST.get('address')
        city = request.POST.get('city')
        state_province = request.POST.get('state_province')
        country = request.POST.get('country')
        website = request.POST.get('website')

        Publisher.objects.create(
            name = name,
            address = address,
            city = city,
            state_province = state_province,
            country = country,
            website = website,

        )
        return HttpResponse("添加出版社成功")
    else:
        # 否则将传输的数据打印
        return render(request,'add_publisher.html',locals())

templates目录下增加add_publisher.html


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加出版社信息title>
head>
<body>
<form  action="{% url 'add_publisher' %}"  method="post" >
    {% csrf_token %}
    名称:<input type="text" name="name"><br>
    地址:<input type="text" name="address"><br>
    城市:<input type="text" name="city"><br>
    省份:<input type="text" name="state_province"><br>
    国家:<input type="text" name="country"><br>
    网站:<input type="text" name="website"><br>
    <input type="submit",name="提交"><br>

form>
body>
html>

使用Django_Form

/hello/urls.py

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


urlpatterns = [
       url(r'^hello/$', views.hello,{'a':123}),
       url(r'^test/$', views.test),
       url(r'^testbase/$', views.test1),
       url(r'^add_publisher/$', views.add_publisher,name='add_publisher'),

]

hello/forms.py

from django import forms

class PublisherForm(forms.Form):

    # label标签代表的是在界面上显示的信息,默认情况下显示的英文
    name = forms.CharField(label='姓名')
    address = forms.CharField(label='地址')
    city = forms.CharField(label='城市')
    state_province = forms.CharField(label='省份')
    country = forms.CharField(label='国家')
    website = forms.URLField(label='网站')

hello\view.py

from hello.forms import PublisherForm
from hello.models import Publisher

def add_publisher(request):
    if request.method == 'POST':
        # 如果是POST提交,去接受用户提交的数据
        # 使用Django_form
        publisher_form = PublisherForm(request.POST)
        if publisher_form.is_valid():
            Publisher.objects.create(
                name = publisher_form.cleaned_data['name'],
                address = publisher_form.cleaned_data['address'],
                city = publisher_form.cleaned_data['city'],
                state_province = publisher_form.cleaned_data['state_province'],
                country = publisher_form.cleaned_data['country'],
                website = publisher_form.cleaned_data['website'],

            )
            return HttpResponse("添加出版社成功")


    else:
        # 否则将传输的数据打印
        publisher_form = PublisherForm()
        return render(request,'add_publisher.html',locals())

templates目录下增加add_publisher.html


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加出版社信息title>
head>
<body>
<form  action="{% url 'add_publisher' %}"  method="post" >
    {% csrf_token %}
    {{ publisher_form.as_p }}   // 将view.py中创建的表单对象传输到模版中,表单中的字段会自动生成,as_p表示的是输出的格式使用p>标签

    <input type="submit" name="提交"><br>

form>
body>
html>

使用ModelForm

/hello/urls.py

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


urlpatterns = [
       url(r'^hello/$', views.hello,{'a':123}),
       url(r'^test/$', views.test),
       url(r'^testbase/$', views.test1),
       url(r'^add_publisher/$', views.add_publisher,name='add_publisher'),

]

hello/forms.py

from django import forms
from hello.models import Publisher

class PublisherForm(forms.ModelForm):

    class Meta:
            model = Publisher
            exclude = ("id",)

hello\view.py

from hello.forms import PublisherForm
from hello.models import Publisher

def add_publisher(request):
    if request.method == 'POST':
        # 如果是POST提交,去接受用户提交的数据
        # 使用Django ModelForm
        publisher_form = PublisherForm(request.POST)
        if publisher_form.is_valid():
            publisher_form.save()
            return HttpResponse("添加出版社成功")

    else:
        # 否则将传输的数据打印
        publisher_form = PublisherForm()
        return render(request,'add_publisher.html',locals())

templates目录下增加add_publisher.html


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加出版社信息title>
head>
<body>
<form  action="{% url 'add_publisher' %}"  method="post" >
    {% csrf_token %}
    {{ publisher_form.as_p }}   // 将view.py中创建的表单对象传输到模版中,表单中的字段会自动生成,as_p表示的是输出的格式使用p>标签

    <input type="submit" name="提交"><br>

form>
body>
html>

参考文档

Django官网
理解Django里的MTV开发模式
Django 1.8 中文站点
Django 1.11 中文站点

你可能感兴趣的:(……【python】)