一周后的重温

2019-05-03 22:06 来源:未知

数据库的配置

Django

 

 

 文化预览

  • Django基本命令
  • 贰 路由陈设系列(UCRUISERLconf)
  • 三 编写视图
  • 四 Template
  • 5 数据库与OSportageM
  • admin的配置

一    django默许补助sqlite,mysql, oracle,postgresql数据库。

     <1> sqlite

            django暗许使用sqlite的数据库,私下认可自带sqlite的数据库驱动 , 引擎名称:django.db.backends.sqlite三

     <2> mysql

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

一 什么是web框架?

框架,即framework,特指为化解二个开放性难题而布署的有着一定约束性的支撑结构,使用框架能够帮你急忙支付特定的体系,容易地说,正是您用旁人搭建好的舞台来做演出。

对此有所的Web应用,本质上实在便是一个socket服务端,用户的浏览器其实正是二个socket客户端。

www.weide1946.com 1www.weide1946.com 2

import socket

def handle_request(client):

    buf = client.recv(1024)
    client.send("HTTP/1.1 200 OKrnrn".encode("utf8"))
    client.send("<h1 style='color:red'>Hello, yuan</h1>".encode("utf8"))

def main():

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('localhost',8001))
    sock.listen(5)

    while True:
        connection, address = sock.accept()
        handle_request(connection)
        connection.close()

if __name__ == '__main__':

    main()

View Code

      最简便的Web应用正是先把HTML用文件保留好,用二个现有的HTTP服务器软件,接收用户请求,从文件中读取HTML,重返。

比如要动态生成HTML,就供给把上述手续本身来促成。可是,接受HTTP请求、解析HTTP请求、发送HTTP响应都是搬运工活,借使大家和好来写这几个底层代码,还没起先写动态HTML呢,就得花个把月去读HTTP标准。

      精确的做法是底层代码由尤其的服务器软件达成,我们用Python专注于生成HTML文书档案。因为咱们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,须求一个统1的接口,让大家专心用Python编写Web业务。

www.weide1946.com,其一接口就是WSGI:Web Server Gateway Interface。

-----------------------------Do a web  framework ourselves---------------------------**

一 什么是web框架?

框架,即framework,特指为消除叁个开放性难题而设计的具备一定约束性的支撑结构,使用框架能够帮你快速支付特定的体系,轻松地说,正是您用外人搭建好的舞台来做演出。

对于有所的Web应用,本质上实在便是贰个socket服务端,用户的浏览器其实正是一个socket客户端。

www.weide1946.com 3www.weide1946.com 4

import socket

def handle_request(client):

    buf = client.recv(1024)
    client.send("HTTP/1.1 200 OKrnrn".encode("utf8"))
    client.send("<h1 style='color:red'>Hello, yuan</h1>".encode("utf8"))

def main():

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('localhost',8001))
    sock.listen(5)

    while True:
        connection, address = sock.accept()
        handle_request(connection)
        connection.close()

if __name__ == '__main__':

    main()

View Code

 

最轻易易行的Web应用正是先把HTML用文件保留好,用一个现存的HTTP服务器软件,接收用户请求,从文件中读取HTML,重返。

假使要动态生成HTML,就供给把上述手续本身来兑现。可是,接受HTTP请求、解析HTTP请求、发送HTTP响应都以搬运工活,固然大家和好来写这一个底层代码,还没起来写动态HTML呢,就得花个把月去读HTTP标准。

      准确的做法是底层代码由特其余服务器软件达成,大家用Python专注于生成HTML文书档案。因为我们不期望接触到TCP连接、HTTP原始请求和响应格式,所以,须求几个联合的接口,让大家专心用Python编写Web业务。

以此接口正是WSGI:Web Server Gateway Interface。

-----------------------------Do a web  framework ourselves---------------------------**

贰    mysql驱动程序

  •    MySQLdb(mysql python)
  •    mysqlclient
  •    MySQL
  •    PyMySQL(纯python的mysql驱动程序)

step 1:

www.weide1946.com 5www.weide1946.com 6

from wsgiref.simple_server import make_server


def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'<h1>Hello, web!</h1>']


httpd = make_server('', 8080, application)

print('Serving HTTP on port 8000...')
# 开始监听HTTP请求:
httpd.serve_forever()

View Code

注意:

www.weide1946.com 7www.weide1946.com 8

整个application()函数本身没有涉及到任何解析HTTP的部分,也就是说,底层代码不需要我们自己编写,
我们只负责在更高层次上考虑如何响应请求就可以了。

application()函数必须由WSGI服务器来调用。有很多符合WSGI规范的服务器,我们可以挑选一个来用。

Python内置了一个WSGI服务器,这个模块叫wsgiref    


application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:

        //environ:一个包含所有HTTP请求信息的dict对象;

        //start_response:一个发送HTTP响应的函数。

在application()函数中,调用:

start_response('200 OK', [('Content-Type', 'text/html')])

就发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次start_response()函数。
start_response()函数接收两个参数,一个是HTTP响应码,一个是一组list表示的HTTP Header,每
个Header用一个包含两个str的tuple表示。

通常情况下,都应该把Content-Type头发送给浏览器。其他很多常用的HTTP Header也应该发送。

然后,函数的返回值b'<h1>Hello, web!</h1>'将作为HTTP响应的Body发送给浏览器。

有了WSGI,我们关心的就是如何从environ这个dict对象拿到HTTP请求信息,然后构造HTML,
通过start_response()发送Header,最后返回Body。

View Code

step 1:

www.weide1946.com 9www.weide1946.com 10

from wsgiref.simple_server import make_server


def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'<h1>Hello, web!</h1>']


httpd = make_server('', 8080, application)

print('Serving HTTP on port 8000...')
# 开始监听HTTP请求:
httpd.serve_forever()

View Code

注意:

www.weide1946.com 11www.weide1946.com 12

整个application()函数本身没有涉及到任何解析HTTP的部分,也就是说,底层代码不需要我们自己编写,
我们只负责在更高层次上考虑如何响应请求就可以了。

application()函数必须由WSGI服务器来调用。有很多符合WSGI规范的服务器,我们可以挑选一个来用。

Python内置了一个WSGI服务器,这个模块叫wsgiref    


application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:

        //environ:一个包含所有HTTP请求信息的dict对象;

        //start_response:一个发送HTTP响应的函数。

在application()函数中,调用:

start_response('200 OK', [('Content-Type', 'text/html')])

就发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次start_response()函数。
start_response()函数接收两个参数,一个是HTTP响应码,一个是一组list表示的HTTP Header,每
个Header用一个包含两个str的tuple表示。

通常情况下,都应该把Content-Type头发送给浏览器。其他很多常用的HTTP Header也应该发送。

然后,函数的返回值b'<h1>Hello, web!</h1>'将作为HTTP响应的Body发送给浏览器。

有了WSGI,我们关心的就是如何从environ这个dict对象拿到HTTP请求信息,然后构造HTML,
通过start_response()发送Header,最后返回Body。

View Code

step 2

www.weide1946.com 13www.weide1946.com 14

print(environ['PATH_INFO'])
    path=environ['PATH_INFO']
    start_response('200 OK', [('Content-Type', 'text/html')])
    f1=open("index1.html","rb")
    data1=f1.read()
    f2=open("index2.html","rb")
    data2=f2.read()

    if path=="/yuan":
        return [data1]
    elif path=="/alex":
        return [data2]
    else:
        return ["<h1>404</h1>".encode('utf8')]

View Code

step3

www.weide1946.com 15www.weide1946.com 16

from wsgiref.simple_server import make_server

def f1():
    f1=open("index1.html","rb")
    data1=f1.read()
    return [data1]

def f2():
    f2=open("index2.html","rb")
    data2=f2.read()
    return [data2]

def application(environ, start_response):

    print(environ['PATH_INFO'])
    path=environ['PATH_INFO']
    start_response('200 OK', [('Content-Type', 'text/html')])


    if path=="/yuan":
        return f1()

    elif path=="/alex":
        return f2()

    else:
        return ["<h1>404</h1>".encode("utf8")]


httpd = make_server('', 8502, application)

print('Serving HTTP on port 8084...')

# 开始监听HTTP请求:
httpd.serve_forever()

View Code

step4

www.weide1946.com 17www.weide1946.com 18

from wsgiref.simple_server import make_server


def f1(req):
    print(req)
    print(req["QUERY_STRING"])

    f1=open("index1.html","rb")
    data1=f1.read()
    return [data1]

def f2(req):

    f2=open("index2.html","rb")
    data2=f2.read()
    return [data2]

import time

def f3(req):        #模版以及数据库

    f3=open("index3.html","rb")
    data3=f3.read()
    times=time.strftime("%Y-%m-%d %X", time.localtime())
    data3=str(data3,"utf8").replace("!time!",str(times))


    return [data3.encode("utf8")]


def routers():

    urlpatterns = (
        ('/yuan',f1),
        ('/alex',f2),
        ("/cur_time",f3)
    )
    return urlpatterns


def application(environ, start_response):

    print(environ['PATH_INFO'])
    path=environ['PATH_INFO']
    start_response('200 OK', [('Content-Type', 'text/html')])


    urlpatterns = routers()
    func = None
    for item in urlpatterns:
        if item[0] == path:
            func = item[1]
            break
    if func:
        return func(environ)
    else:
        return ["<h1>404</h1>".encode("utf8")]

httpd = make_server('', 8518, application)

print('Serving HTTP on port 8084...')

# 开始监听HTTP请求:

httpd.serve_forever()

View Code

一同们,神不知鬼不觉大家友好早就写出多少个web框架啦!

三     在django的种类中会暗许使用sqlite数据库,在settings里有如下设置:

www.weide1946.com 19

若果大家想要改换数据库,必要修改如下:

www.weide1946.com 20

 1 DATABASES = {
 2 
 3     'default': {
 4 
 5         'ENGINE': 'django.db.backends.mysql', 
 6 
 7         'NAME': 'books',    #你的数据库名称
 8 
 9         'USER': 'root',   #你的数据库用户名
10 
11         'PASSWORD': '', #你的数据库密码
12 
13         'HOST': '', #你的数据库主机,留空默认为localhost
14 
15         'PORT': '3306', #你的数据库端口
16 
17     }
18 
19 }

注意:

www.weide1946.com 21www.weide1946.com 22

 1 NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建
 2 
 3 USER和PASSWORD分别是数据库的用户名和密码。
 4 
 5 设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。
 6 
 7 然后,启动项目,会报错:no module named MySQLdb
 8 
 9 这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb对于py3有很大问题,所以我们需要的驱动是PyMySQL
10 
11 所以,我们只需要找到项目名文件下的__init__,在里面写入:
12 
13 import pymysql
14 pymysql.install_as_MySQLdb()
15 
16 问题解决!

View Code

step 2

www.weide1946.com 23www.weide1946.com 24

print(environ['PATH_INFO'])
    path=environ['PATH_INFO']
    start_response('200 OK', [('Content-Type', 'text/html')])
    f1=open("index1.html","rb")
    data1=f1.read()
    f2=open("index2.html","rb")
    data2=f2.read()

    if path=="/yuan":
        return [data1]
    elif path=="/alex":
        return [data2]
    else:
        return ["<h1>404</h1>".encode('utf8')]

View Code

二 MVC和MTV模式

Django的M电视机方式本质是各组件之间为了保持松耦合关系,Django的MTV分别表示:

       Model(模型):负担作业对象与数据库的对象(O猎豹CS6M)

       Template(模版):肩负什么把页面展现给用户

       View(视图):担任作业逻辑,并在合适的时候调用Model和Template

       别的,Django还有四个url分发器,它的机能是将一个个UCR-VL的页面请求分发给分裂的view管理,view再调用相应的Model和Template

www.weide1946.com 25

回来顶部

OXC90M(对象关联映射)

用来落实面向对象编制程序语言里差异体系系统的数目里面包车型大巴转变,换言之,正是用面向对象的秘籍去操作数据库的始建表以及增加和删除改查等操作。

可取: 一ORAV4M使得我们的通用数据库交互变得轻巧易行,而且完全不用思虑该死的SQL语句。快捷支付,因此而来。

          二方可制止某些菜鸟程序员写sql语句带来的性攻讦题。

            比方我们查询User表中的全体字段:

www.weide1946.com 26

 菜鸟或然会用select * from  auth_user,那样会因为多了一个相称动作而影响成效的。

 缺点:1  性质兼备就义,不过今后的各类OCR-VM框架都在品尝各个艺术,举个例子缓存,延迟加载登来缓和这几个标题。效果很分明。

          2 对于个别复杂查询,O大切诺基M还是鞭长莫及,为了化解那一个题目,OLANDM一般也帮助写raw sql。

          叁  通过QuerySet的query属性查询相应操作的sql语句

1 author_obj=models.Author.objects.filter(id=2)
2 print(author_obj.query)

 上面要开始学习Django OCRUISERM语法了,为了更加好的通晓,大家来做1个主导的 书籍/小编/出版商 数据库结构。 大家如此做是因为 那是三个明显的事例,诸多SQL有关的书本也常用这一个比喻。

step3

www.weide1946.com 27www.weide1946.com 28

from wsgiref.simple_server import make_server

def f1():
    f1=open("index1.html","rb")
    data1=f1.read()
    return [data1]

def f2():
    f2=open("index2.html","rb")
    data2=f2.read()
    return [data2]

def application(environ, start_response):

    print(environ['PATH_INFO'])
    path=environ['PATH_INFO']
    start_response('200 OK', [('Content-Type', 'text/html')])


    if path=="/yuan":
        return f1()

    elif path=="/alex":
        return f2()

    else:
        return ["<h1>404</h1>".encode("utf8")]


httpd = make_server('', 8502, application)

print('Serving HTTP on port 8084...')

# 开始监听HTTP请求:
httpd.serve_forever()

View Code

Django基本命令

1、创立多个django project

1
django-admin.py startproject mysite

 当前目录下会生成mysite的工程,目录结构如下:

        www.weide1946.com 29

  • manage.py ----- Django项目里面包车型客车工具,通过它能够调用django shell和数据库等。
  • settings.py ---- 包括了类别的暗中同意设置,包涵数据库音信,调节和测试标记以及任何一些行事的变量。
  • urls.py ----- 担负把U奥迪Q5L形式映射到应用程序。

2、在mysite目录下开创应用,比方blog:

1
python manage.py startapp blog

        www.weide1946.com 30

3、启动django项目

1
python manage.py runserver 8080

       那样我们的django就开动起来了!当大家访问:

       www.weide1946.com 31

4、同步转移数据库表或字段

www.weide1946.com 32

'''
    python manage.py syncdb

    注意:Django 1.7.1 及以上的版本需要用以下命令
    python manage.py makemigrations
    python manage.py migrate

'''

www.weide1946.com 33

这种办法能够创制表,当你在models.py中新添了类时,运维它就足以自行在数据库中创制表了,不用手动创制。

五、清空数据库

1
python manage.py flush

 此命令会询问是 yes 依然 no, 采取 yes 会把多少总体清空掉,只留下空表。

陆、成立一流管理员

www.weide1946.com 34

'''
    python manage.py createsuperuser

    # 按照提示输入用户名和对应的密码就好了邮箱可以留空,用户名和密码必填

    # 修改 用户密码可以用:
    python manage.py changepassword username

'''

www.weide1946.com 35

7、Django 项目条件终端

1
python manage.py shell

本条命令和 直接运转 python 进入 shell 的区分是:你能够在那么些 shell 里面调用当前项目的 models.py 中的 API,对于操作数据的测试非凡便宜。

捌、Django 项目条件终端

ython manage.py dbshell

Django 会自动进入在settings.py中安装的数据库,假如是 MySQL 或 postgreSQL,会必要输入数据库用户密码。

在那几个极端能够进行数据库的SQL语句。假如您对SQL比较了解,也许喜欢这种形式。

9、越多命令

1
python manage.py

 查看全数的一声令下,忘记子名称的时候特别有用。

10 static配置

#3、STATIC文件还可以配置STATICFILES_DIRS,指定额外的静态文件存储位置。
    #  STATIC_URL的含义与MEDIA_URL类似。

    # ----------------------------------------------------------------------------
    #注意1:
        #为了后端的更改不会影响前端的引入,避免造成前端大量修改

        STATIC_URL = '/static/'               #引用名
        STATICFILES_DIRS = (
            os.path.join(BASE_DIR,"statics")  #实际名 ,即实际文件夹的名字
        )

        #django对引用名和实际名进行映射,引用时,只能按照引用名来,不能按实际名去找
        #<script src="/statics/jquery-3.1.1.js"></script>
        #------error-----不能直接用,必须用STATIC_URL = '/static/':
        #<script src="/static/jquery-3.1.1.js"></script>

    #注意2(statics文件夹写在不同的app下,静态文件的调用):

        STATIC_URL = '/static/'

        STATICFILES_DIRS=(
            ('hello',os.path.join(BASE_DIR,"app01","statics")) ,
        )

        #<script src="/static/hello/jquery-1.8.2.min.js"></script>

    #注意3:
        STATIC_URL = '/static/'
        {% load staticfiles %}
       # <script src={% static "jquery-1.8.2.min.js" %}></script>

2路由布署体系(U君越Lconf)

ULANDL配置(URubiconLconf)就好像Django 所支撑网址的目录。它的原形是UPAJEROL与要为该URubiconL调用的视图函数之间的映射表;你正是以那种措施告知Django,对于那几个U途达L调用那段代码,对于那么些U大切诺基L调用那段代码。

    '''

    urlpatterns = [
         url(正则表达式, views视图函数,参数,别名),
]


参数说明:

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

    '''

表(模型)的创建:

实例:我们来假诺下边那个概念,字段和关系

作者模型:2个小编有真名。

作者详细模型:把小编的详细情形放到详细情形表,包罗性别,email地址和出寿辰期,小编详细的情况模型和作者模型之间是一定的关系(one-to-one)(类似于种种人和他的身份证之间的涉及),在大多动静下大家平昔不供给将她们拆分成两张表,这里只是引出一对一的定义。

出版商模型:出版商盛名称,地址,所在城市,省,国家和网址。

图书模型:书籍有书名和出版日期,1本书恐怕会有三个小编,七个小编也得以写多本书,所以小编和图书的关系正是多对多的涉嫌关系(many-to-many),一本书只应该由3个出版商出版,所以出版商和书籍是1对多关系关系(one-to-many),也被称作外键。

www.weide1946.com 36www.weide1946.com 37

 1 from django.db import models<br>
 2 class Publisher(models.Model):
 3     name = models.CharField(max_length=30, verbose_name="名称")
 4     address = models.CharField("地址", max_length=50)
 5     city = models.CharField('城市',max_length=60)
 6     state_province = models.CharField(max_length=30)
 7     country = models.CharField(max_length=50)
 8     website = models.URLField()
 9  
10     class Meta:
11         verbose_name = '出版商'
12         verbose_name_plural = verbose_name
13  
14     def __str__(self):
15         return self.name
16  
17 class Author(models.Model):
18     name = models.CharField(max_length=30)
19     def __str__(self):
20         return self.name
21  
22 class AuthorDetail(models.Model):
23     sex = models.BooleanField(max_length=1, choices=((0, '男'),(1, '女'),))
24     email = models.EmailField()
25     address = models.CharField(max_length=50)
26     birthday = models.DateField()
27     author = models.OneToOneField(Author)
28  
29 class Book(models.Model):
30     title = models.CharField(max_length=100)
31     authors = models.ManyToManyField(Author)
32     publisher = models.ForeignKey(Publisher)
33     publication_date = models.DateField()
34     price=models.DecimalField(max_digits=5,decimal_places=2,default=10)
35     def __str__(self):
36         return self.title

View Code

注意1:记得在settings里的INSTALLED_APPS中到场'app01',然后再一齐数据库。

注意2: models.ForeignKey("Publish") & models.ForeignKey(Publish)

解析代码:

       <1>  各个数据模型都以django.db.models.Model的子类,它的父类Model包括了装有要求的和数据库交互的点子。并提供了一个简要介绍美貌的概念数据库字段的语法。

       <二>  每一种模型也正是单个数据库表(多对多涉及区别,会多生成一张关系表),每个属性也是以此表中的字段。属性名正是字段名,它的等级次序(比如CharField)相当于数据库的字段类型(比方varchar)。大家能够小心下其余的体系都和数据Curry的什么样字段对应。

       <叁>  模型之间的二种关系:壹对壹,一对多,多对多。

             1对一:实质就是在主外键(author_id正是foreign key)的关联基础上,给外键加了贰个UNIQUE=True的属性;

             一对多:便是主外键关系;(foreign key)

             多对多:(ManyToManyField) 自动创立第二张表(当然大家也足以团结创办第一张表:多个foreign key)

       <4>  模型常用的字段类型参数

www.weide1946.com 38www.weide1946.com 39

<1> CharField
        #字符串字段, 用于较短的字符串.
        #CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.

<2> IntegerField
       #用于保存一个整数.

<3> FloatField
        # 一个浮点数. 必须 提供两个参数:
        #
        # 参数    描述
        # max_digits    总位数(不包括小数点和符号)
        # decimal_places    小数位数
                # 举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段:
                #
                # models.FloatField(..., max_digits=5, decimal_places=2)
                # 要保存最大值一百万(小数点后保存10位)的话,你要这样定义:
                #
                # models.FloatField(..., max_digits=19, decimal_places=10)
                # admin 用一个文本框(<input type="text">)表示该字段保存的数据.

<4> AutoField
        # 一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段; 
        # 自定义一个主键:my_id=models.AutoField(primary_key=True)
        # 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.

<5> BooleanField
        # A true/false field. admin 用 checkbox 来表示此类字段.

<6> TextField
        # 一个容量很大的文本字段.
        # admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).

<7> EmailField
        # 一个带有检查Email合法性的 CharField,不接受 maxlength 参数.

<8> DateField
        # 一个日期字段. 共有下列额外的可选参数:
        # Argument    描述
        # auto_now    当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳.
        # auto_now_add    当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.
        #(仅仅在admin中有意义...)

<9> DateTimeField
        #  一个日期时间字段. 类似 DateField 支持同样的附加选项.

<10> ImageField
        # 类似 FileField, 不过要校验上传对象是否是一个合法图片.#它有两个可选参数:height_field和width_field,
        # 如果提供这两个参数,则图片将按提供的高度和宽度规格保存.     
<11> FileField
     # 一个文件上传字段.
     #要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime #formatting, 
     #该格式将被上载文件的 date/time 
     #替换(so that uploaded files don't fill up the given directory).
     # admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) .

     #注意:在一个 model 中使用 FileField 或 ImageField 需要以下步骤:
            #(1)在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件. 
            # (出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对 
            #  WEB服务器用户帐号是可写的.
            #(2) 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django
            # 使用 MEDIA_ROOT 的哪个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT). 
            # 出于习惯你一定很想使用 Django 提供的 get_<#fieldname>_url 函数.举例来说,如果你的 ImageField 
            # 叫作 mug_shot, 你就可以在模板中以 {{ object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径.

<12> URLField
      # 用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且
      # 没有返回404响应).
      # admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)

<13> NullBooleanField
       # 类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项
       # admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes" 和 "No" ) 来表示这种字段数据.

<14> SlugField
       # "Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.#它们通常用于URLs
       # 若你使用 Django 开发版本,你可以指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50.  #在
       # 以前的 Django 版本,没有任何办法改变50 这个长度.
       # 这暗示了 db_index=True.
       # 它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-#populate 
       # the slug, via JavaScript,in the object's admin form: models.SlugField
       # (prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields.

<13> XMLField
        #一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径.

<14> FilePathField
        # 可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的.
        # 参数    描述
        # path    必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目. 
        # Example: "/home/images".
        # match    可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名.  
        # 注意这个正则表达式只会应用到 base filename 而不是
        # 路径全名. Example: "foo.*.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif.
        # recursive可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录.
        # 这三个参数可以同时使用.
        # match 仅应用于 base filename, 而不是路径全名. 那么,这个例子:
        # FilePathField(path="/home/images", match="foo.*", recursive=True)
        # ...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif

<15> IPAddressField
        # 一个字符串形式的 IP 地址, (i.e. "24.124.1.30").
<16># CommaSeparatedIntegerField
        # 用于存放逗号分隔的整数值. 类似 CharField, 必须要有maxlength参数.

View Code

      <5>  菲尔德主要参数

www.weide1946.com 40www.weide1946.com 41

<1> null : 数据库中字段是否可以为空

    <2> blank: django的 Admin 中添加数据时是否可允许空值

    <3> default:设定缺省值

    <4> editable:如果为假,admin模式下将不能改写。缺省为真

    <5> primary_key:设置主键,如果没有设置django创建表时会自动加上:
        id = meta.AutoField('ID', primary_key=True)
        primary_key=True implies blank=False, null=False and unique=True. Only one
        primary key is allowed on an object.

    <6> unique:数据唯一

    <7> verbose_name  Admin中字段的显示名称

    <8> validator_list:有效性检查。非有效产生 django.core.validators.ValidationError 错误


    <9> db_column,db_index 如果为真将为此字段创建索引

    <10>choices:一个用来选择值的2维元组。第一个值是实际存储的值,第二个用来方便进行选择。
                如SEX_CHOICES= (( ‘F’,'Female’),(‘M’,'Male’),)
                gender = models.CharField(max_length=2,choices = SEX_CHOICES)

View Code

step4

www.weide1946.com 42www.weide1946.com 43

from wsgiref.simple_server import make_server


def f1(req):
    print(req)
    print(req["QUERY_STRING"])

    f1=open("index1.html","rb")
    data1=f1.read()
    return [data1]

def f2(req):

    f2=open("index2.html","rb")
    data2=f2.read()
    return [data2]

import time

def f3(req):        #模版以及数据库

    f3=open("index3.html","rb")
    data3=f3.read()
    times=time.strftime("%Y-%m-%d %X", time.localtime())
    data3=str(data3,"utf8").replace("!time!",str(times))


    return [data3.encode("utf8")]


def routers():

    urlpatterns = (
        ('/yuan',f1),
        ('/alex',f2),
        ("/cur_time",f3)
    )
    return urlpatterns


def application(environ, start_response):

    print(environ['PATH_INFO'])
    path=environ['PATH_INFO']
    start_response('200 OK', [('Content-Type', 'text/html')])


    urlpatterns = routers()
    func = None
    for item in urlpatterns:
        if item[0] == path:
            func = item[1]
            break
    if func:
        return func(environ)
    else:
        return ["<h1>404</h1>".encode("utf8")]

httpd = make_server('', 8518, application)

print('Serving HTTP on port 8084...')

# 开始监听HTTP请求:

httpd.serve_forever()

View Code

同路人们,无声无息大家团结早就写出二个web框架啦!

二.一 U福特ExplorerLconf的正则字符串参数

表的操作(增加和删除改查):

**-------------------------------------增(create  ,  save) -------------------------------**

 1 from app01.models import *
 2 
 3     #create方式一:   Author.objects.create(name='Alvin')
 4 
 5     #create方式二:   Author.objects.create(**{"name":"alex"})
 6 
 7     #save方式一:     author=Author(name="alvin")
 8                     author.save()
 9 
10     #save方式二:     author=Author()
11                     author.name="alvin"
12                     author.save()

对于一对多、多对多的操作:

www.weide1946.com 44www.weide1946.com 45

 1 #一对多(ForeignKey):
 2 
 3     #方式一: 由于绑定一对多的字段,比如publish,存到数据库中的字段名叫publish_id,所以我们可以直接给这个
 4     #       字段设定对应值:
 5            Book.objects.create(title='php',
 6                                publisher_id=2,   #这里的2是指为该book对象绑定了Publisher表中id=2的行对象
 7                                publication_date='2017-7-7',
 8                                price=99)
 9 
10 
11     #方式二:
12     #       <1> 先获取要绑定的Publisher对象:
13         pub_obj=Publisher(name='河大出版社',address='保定',city='保定',
14                 state_province='河北',country='China',website='http://www.hbu.com')
15     OR  pub_obj=Publisher.objects.get(id=1)
16 
17     #       <2>将 publisher_id=2 改为  publisher=pub_obj
18 
19 #多对多(ManyToManyField()):
20 
21     author1=Author.objects.get(id=1)
22     author2=Author.objects.filter(name='alvin')[0]
23     book=Book.objects.get(id=1)
24     book.authors.add(author1,author2)
25     #等同于:
26     book.authors.add(*[author1,author2])
27     book.authors.remove(*[author1,author2])
28     #-------------------
29     book=models.Book.objects.filter(id__gt=1)
30     authors=models.Author.objects.filter(id=1)[0]
31     authors.book_set.add(*book)
32     authors.book_set.remove(*book)
33     #-------------------
34     book.authors.add(1)
35     book.authors.remove(1)
36     authors.book_set.add(1)
37     authors.book_set.remove(1)
38 
39 #注意: 如果第三张表是通过models.ManyToManyField()自动创建的,那么绑定关系只有上面一种方式
40 #     如果第三张表是自己创建的:
41      class Book2Author(models.Model):
42             author=models.ForeignKey("Author")
43             Book=  models.ForeignKey("Book")
44 #     那么就还有一种方式:
45             author_obj=models.Author.objects.filter(id=2)[0]
46             book_obj  =models.Book.objects.filter(id=3)[0]
47 
48             s=models.Book2Author.objects.create(author_id=1,Book_id=2)
49             s.save()
50             s=models.Book2Author(author=author_obj,Book_id=1)
51             s.save()

View Code

**-----------------------------------------删(delete) ---------------------------------------------**

1 >>> Book.objects.filter(id=1).delete()
2 (3, {'app01.Book_authors': 2, 'app01.Book': 1})

咱俩外表上剔除了一条音信,实际却删除了三条,因为大家删除的这本书在Book_authors表中有两条相关音信,那种删除格局便是django暗中同意的级联删除。

比方是多对多的涉及: remove()和clear()方法: 

 1 #正向
 2 book = models.Book.objects.filter(id=1)
 3 
 4 #删除第三张表中和女孩1关联的所有关联信息
 5 book.author.clear()        #清空与book中id=1 关联的所有数据
 6 book.author.remove(2)  #可以为id
 7 book.author.remove(*[1,2,3,4])     #可以为列表,前面加*
 8 
 9 #反向
10 author = models.Author.objects.filter(id=1)
11 author.book_set.clear() #清空与boy中id=1 关联的所有数据

**-----------------------------------------改(update和save) ----------------------------------------**

实例:

www.weide1946.com 46

注意:

<1> 第三种办法修改不能用get的开始和结果是:update是QuerySet对象的点子,get重临的是二个model对象,它并未有update方法,而filter再次回到的是2个QuerySet对象(filter里面包车型地铁规格可能有多少个原则适合,比方name='alvin',恐怕有八个name='alvin'的行数据)。

<2>在“插入和更新数据”小节中,我们有提到模型的save()方法,这个方法会更新一行里的所有列。 而某些情况下,我们只需要更新行里的某几列。

www.weide1946.com 47www.weide1946.com 48

 1 #---------------- update方法直接设定对应属性----------------
 2     models.Book.objects.filter(id=3).update(title="PHP")
 3     ##sql:
 4     ##UPDATE "app01_book" SET "title" = 'PHP' WHERE "app01_book"."id" = 3; args=('PHP', 3)
 5 
 6 
 7 #--------------- save方法会将所有属性重新设定一遍,效率低-----------
 8     obj=models.Book.objects.filter(id=3)[0]
 9     obj.title="Python"
10     obj.save()
11 # SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price", 
12 # "app01_book"."color", "app01_book"."page_num", 
13 # "app01_book"."publisher_id" FROM "app01_book" WHERE "app01_book"."id" = 3 LIMIT 1; 
14 # 
15 # UPDATE "app01_book" SET "title" = 'Python', "price" = 3333, "color" = 'red', "page_num" = 556,
16 # "publisher_id" = 1 WHERE "app01_book"."id" = 3;

View Code

  在这些例子里大家得以看来Django的save()方法立异了不可是title列的值,还有立异了独具的列。 若title以外的列有相当大大概会被其余的经过所退换的景况下,只改动title列分明是越来越精明的。改造某一点名的列,我们能够调用结果集(QuerySet)对象的update()方法,与之等同的SQL语句变得更飞快,并且不会唤起竞态条件。

其余,update()方法对于别的结果集(QuerySet)均有效,那代表你能够而且更新多条记录update()方法会再次回到3个整型数值,表示受影响的笔录条数。

瞩目,这里因为update重临的是三个整形,所以没办法用query属性;对于每一次创设3个目标,想呈现相应的raw sql,要求在settings加上日志记录部分:

www.weide1946.com 49www.weide1946.com 50

 1 LOGGING = {
 2     'version': 1,
 3     'disable_existing_loggers': False,
 4     'handlers': {
 5         'console':{
 6             'level':'DEBUG',
 7             'class':'logging.StreamHandler',
 8         },
 9     },
10     'loggers': {
11         'django.db.backends': {
12             'handlers': ['console'],
13             'propagate': True,
14             'level':'DEBUG',
15         },
16     }
17 }
18 
19 LOGGING

View Code

小心:假设是多对多的改:

1 obj=Book.objects.filter(id=1)[0]
2     author=Author.objects.filter(id__gt=2)
3 
4     obj.author.clear()
5     obj.author.add(*author)

---------------------------------------查(filter,value等) -------------------------------------**

---------->查询API:

www.weide1946.com 51www.weide1946.com 52

# 查询相关API:

#  <1>filter(**kwargs):      它包含了与所给筛选条件相匹配的对象

#  <2>all():                 查询所有结果

#  <3>get(**kwargs):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。

#-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()--------

#  <4>values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列

#  <5>exclude(**kwargs):     它包含了与所给筛选条件不匹配的对象

#  <6>order_by(*field):      对查询结果排序

#  <7>reverse():             对查询结果反向排序

#  <8>distinct():            从返回结果中剔除重复纪录

#  <9>values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

#  <10>count():              返回数据库中匹配查询(QuerySet)的对象数量。

# <11>first():               返回第一条记录

# <12>last():                返回最后一条记录

#  <13>exists():             如果QuerySet包含数据,就返回True,否则返回False。

View Code

补充:

www.weide1946.com 53www.weide1946.com 54

#扩展查询,有时候DJANGO的查询API不能方便的设置查询条件,提供了另外的扩展查询方法extra:
#extra(select=None, where=None, params=None, tables=None,order_by=None, select_params=None

(1)  Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
(2)  Blog.objects.extra(
        select=SortedDict([('a', '%s'), ('b', '%s')]),
        select_params=('one', 'two'))

(3)  q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
     q = q.extra(order_by = ['-is_recent'])

(4)  Entry.objects.extra(where=['headline=%s'], params=['Lennon'])  

extra

View Code

---------->惰性机制:

所谓惰性机制:Publisher.objects.all()大概.filter()等都只是回来了1个QuerySet(查询结果集对象),它并不会立时推行sql,而是当调用QuerySet的时候才实施。

QuerySet特点:

       <1>  可迭代的

       <2>  可切片

www.weide1946.com 55www.weide1946.com 56

 1 #objs=models.Book.objects.all()#[obj1,obj2,ob3...]
 2 
 3     #QuerySet:   可迭代
 4 
 5     # for obj in objs:#每一obj就是一个行对象
 6     #     print("obj:",obj)
 7     # QuerySet:  可切片
 8 
 9     # print(objs[1])
10     # print(objs[1:4])
11     # print(objs[::-1])

View Code

QuerySet的火速使用:

www.weide1946.com 57www.weide1946.com 58

<1>Django的queryset是惰性的

     Django的queryset对应于数据库的若干记录(row),通过可选的查询来过滤。例如,下面的代码会得
     到数据库中名字为‘Dave’的所有的人:person_set = Person.objects.filter(first_name="Dave")
     上面的代码并没有运行任何的数据库查询。你可以使用person_set,给它加上一些过滤条件,或者将它传给某个函数,
     这些操作都不会发送给数据库。这是对的,因为数据库查询是显著影响web应用性能的因素之一。

<2>要真正从数据库获得数据,你可以遍历queryset或者使用if queryset,总之你用到数据时就会执行sql.
   为了验证这些,需要在settings里加入 LOGGING(验证方式)
        obj=models.Book.objects.filter(id=3)
        # for i in obj:
        #     print(i)

        # if obj:
        #     print("ok")

<3>queryset是具有cache的
     当你遍历queryset时,所有匹配的记录会从数据库获取,然后转换成Django的model。这被称为执行
    (evaluation).这些model会保存在queryset内置的cache中,这样如果你再次遍历这个queryset,
     你不需要重复运行通用的查询。
        obj=models.Book.objects.filter(id=3)

        # for i in obj:
        #     print(i)
                          ## models.Book.objects.filter(id=3).update(title="GO")
                          ## obj_new=models.Book.objects.filter(id=3)
        # for i in obj:
        #     print(i)   #LOGGING只会打印一次

<4>
     简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些
     数据!为了避免这个,可以用exists()方法来检查是否有数据:

            obj = Book.objects.filter(id=4)
            #  exists()的检查可以避免数据放入queryset的cache。
            if obj.exists():
                print("hello world!")

<5>当queryset非常巨大时,cache会成为问题

     处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统
     进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法
     来获取数据,处理完数据就将其丢弃。
        objs = Book.objects.all().iterator()
        # iterator()可以一次只从数据库获取少量数据,这样可以节省内存
        for obj in objs:
            print(obj.name)
        #BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了
        for obj in objs:
            print(obj.name)

     #当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使
     #用iterator()的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询

总结:
    queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。
使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能
会造成额外的数据库查询。

View Code

---------->对象查询,单表条件查询,多表口径关联合检查询

www.weide1946.com 59www.weide1946.com 60

#--------------------对象形式的查找--------------------------
    # 正向查找
    ret1=models.Book.objects.first()
    print(ret1.title)
    print(ret1.price)
    print(ret1.publisher)
    print(ret1.publisher.name)  #因为一对多的关系所以ret1.publisher是一个对象,而不是一个queryset集合

    # 反向查找
    ret2=models.Publish.objects.last()
    print(ret2.name)
    print(ret2.city)
    #如何拿到与它绑定的Book对象呢?
    print(ret2.book_set.all()) #ret2.book_set是一个queryset集合

#---------------了不起的双下划线(__)之单表条件查询----------------

#    models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
#
#    models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
#    models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
#
#    models.Tb1.objects.filter(name__contains="ven")
#    models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
#
#    models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and
#
#    startswith,istartswith, endswith, iendswith,

#----------------了不起的双下划线(__)之多表条件关联查询---------------

# 正向查找(条件)

#     ret3=models.Book.objects.filter(title='Python').values('id')
#     print(ret3)#[{'id': 1}]

      #正向查找(条件)之一对多

      ret4=models.Book.objects.filter(title='Python').values('publisher__city')
      print(ret4)  #[{'publisher__city': '北京'}]

      #正向查找(条件)之多对多
      ret5=models.Book.objects.filter(title='Python').values('author__name')
      print(ret5)
      ret6=models.Book.objects.filter(author__name="alex").values('title')
      print(ret6)

      #注意
      #正向查找的publisher__city或者author__name中的publisher,author是book表中绑定的字段
      #一对多和多对多在这里用法没区别

# 反向查找(条件)

    #反向查找之一对多:
    ret8=models.Publisher.objects.filter(book__title='Python').values('name')
    print(ret8)#[{'name': '人大出版社'}]  注意,book__title中的book就是Publisher的关联表名

    ret9=models.Publisher.objects.filter(book__title='Python').values('book__authors')
    print(ret9)#[{'book__authors': 1}, {'book__authors': 2}]

    #反向查找之多对多:
    ret10=models.Author.objects.filter(book__title='Python').values('name')
    print(ret10)#[{'name': 'alex'}, {'name': 'alvin'}]

    #注意
    #正向查找的book__title中的book是表名Book
    #一对多和多对多在这里用法没区别

View Code

专注:条件查询即与目标查询相应,是指在filter,values等方法中的通过__来鲜明询问条件。

---------->聚合查询和分组查询

<1> aggregate(*args,**kwargs):

   通过对QuerySet举行测算,重临1个聚合值的字典。aggregate()中每贰个参数都钦命叁个分包在字典中的重返值。即在查询集上生成聚合。

www.weide1946.com 61www.weide1946.com 62

from django.db.models import Avg,Min,Sum,Max

从整个查询集生成统计值。比如,你想要计算所有在售书的平均价钱。Django的查询语法提供了一种方式描述所有
图书的集合。

>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35}

aggregate()子句的参数描述了我们想要计算的聚合值,在这个例子中,是Book模型中price字段的平均值

aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的
标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定
一个名称,可以向聚合子句提供它:
>>> Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}


如果你也想知道所有图书价格的最大值和最小值,可以这样查询:
>>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}

View Code

<2> annotate(*args,**kwargs):

   能够透过总计查询结果中每贰个对象所关联的靶子群集,从而得出计算值(也能够是平均值或总和),即为查询集的每1项生成聚合。

       查询alex出的书总价格                   

www.weide1946.com 63

        查询各样小编出的书的总价格,这里就关系到分组了,分组条件是authors__name

www.weide1946.com 64

         查询各样出版社最有利的书价是不怎么

www.weide1946.com 65

---------->F查询和Q查询

单独靠单纯的主要字参数查询已经很难满足查询需要。此时Django为大家提供了F和Q查询:

www.weide1946.com 66www.weide1946.com 67

 1 # F 使用查询条件的值,专门取对象中某列值的操作
 2 
 3     # from django.db.models import F
 4     # models.Tb1.objects.update(num=F('num') 1)
 5 
 6 
 7 # Q 构建搜索条件
 8     from django.db.models import Q
 9 
10     #1 Q对象(django.db.models.Q)可以对关键字参数进行封装,从而更好地应用多个查询
11     q1=models.Book.objects.filter(Q(title__startswith='P')).all()
12     print(q1)#[<Book: Python>, <Book: Perl>]
13 
14     # 2、可以组合使用&,|操作符,当一个操作符是用于两个Q的对象,它产生一个新的Q对象。
15     Q(title__startswith='P') | Q(title__startswith='J')
16 
17     # 3、Q对象可以用~操作符放在前面表示否定,也可允许否定与不否定形式的组合
18     Q(title__startswith='P') | ~Q(pub_date__year=2005)
19 
20     # 4、应用范围:
21 
22     # Each lookup function that takes keyword-arguments (e.g. filter(),
23     #  exclude(), get()) can also be passed one or more Q objects as
24     # positional (not-named) arguments. If you provide multiple Q object
25     # arguments to a lookup function, the arguments will be “AND”ed
26     # together. For example:
27 
28     Book.objects.get(
29         Q(title__startswith='P'),
30         Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
31     )
32 
33     #sql:
34     # SELECT * from polls WHERE question LIKE 'P%'
35     #     AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
36 
37     # import datetime
38     # e=datetime.date(2005,5,6)  #2005-05-06
39 
40     # 5、Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面。
41     # 正确:
42     Book.objects.get(
43         Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
44         title__startswith='P')
45     # 错误:
46     Book.objects.get(
47         question__startswith='P',
48         Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))

View Code

二 MVC和MTV模式

闻名海外的MVC方式:所谓MVC即是把web应用分为模型(M),调节器(C),视图(V)三层;他们中间以一种插件似的,松耦合的法子连接在一块儿。

模型肩负作业对象与数据库的对象(OKugaM),视图担任与用户的互动(页面),调整器(C)接受用户的输入调用模型和视图完成用户的央浼。

                   www.weide1946.com 68

Django的M电视形式本质上与MVC方式尚未什么差异,也是各组件之间为了保证松耦合关系,只是概念上某个许分化,Django的M电视分别表示:

       Model(模型):负担作业对象与数据库的目的(O普拉多M)

       Template(模版):担负什么把页面呈现给用户

       View(视图):肩负作业逻辑,并在适用的时候调用Model和Template

       其余,Django还有3个url分发器,它的效应是将2个个U猎豹CS六L的页面请求分发给分歧的view管理,view再调用相应的Model和Template

www.weide1946.com 69

二.1.一 轻松安插

www.weide1946.com 70

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),
]

www.weide1946.com 71

www.weide1946.com 72

    '''
    NOTE:
    1 一旦匹配成功则不再继续
    2 若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。
    3 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
    4 每个正则表达式前面的'r' 是可选的但是建议加上。

一些请求的例子:

    /articles/2005/3/ 不匹配任何URL 模式,因为列表中的第三个模式要求月份应该是两个数字。
    /articles/2003/ 将匹配列表中的第一个模式不是第二个,因为模式按顺序匹配,第一个会首先测试是否匹配。
    /articles/2005/03/ 请求将匹配列表中的第三个模式。Django 将调用函数
                       views.month_archive(request, '2005', '03')。
    '''

www.weide1946.com 73

#设置项是否开启URL访问地址后面不为/跳转至带有/的路径
APPEND_SLASH=True

 

raw sql

django中models的操作,也是调用了OLX570M框架来兑现的,pymysql 恐怕mysqldb,所以我们也足以运用原生的SQL语句来操作数据库!

 

 3 django的流程和命令行工具

二.壹.二 闻明分组(named group)

下面的以身作则使用简单的、未有命名的正则表明式组(通过圆括号)来捕获U汉兰达L 中的值并以地点参数字传送递给视图。在越来越尖端的用法中,能够使用命名的正则表达式组来捕获U奥德赛L 中的值并以关键字 参数字传送递给视图。

在Python 正则表明式中,命名正则表明式组的语法是(?P<name>pattern),其中name 是组的名目,pattern 是要合作的形式。

上面是以上U奥迪Q3Lconf 使用命名组的重写:

www.weide1946.com 74

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),
]

www.weide1946.com 75

以此落成与目前的言传身教完全相同,唯有八个轻微的差异:捕获的值作为主要字参数而不是岗位参数字传送递给视图函数。举个例子:

    /articles/2005/03/    
    请求将调用views.month_archive(request, year='2005', month='03')函数
    /articles/2003/03/03/ 
    请求将调用函数views.article_detail(request, year='2003', month='03', day='03')。

在实质上采取中,那意味你的UOdysseyLconf 会尤其显著且不轻便发生参数顺序难题的失实 —— 你能够在你的视图函数定义中重新布置参数的依次。当然,这几个收益是以简洁为代价;有个别开采职员感到命名组语法丑陋而麻烦。

django落到实处流程

www.weide1946.com 76www.weide1946.com 77

django
    #安装: pip3 install django

          添加环境变量

    #1  创建project
       django-admin startproject mysite

       ---mysite

          ---settings.py
          ---url.py
          ---wsgi.py

       ---- manage.py(启动文件)  

    #2  创建APP       
       python mannage.py startapp  app01

    #3  settings配置

       TEMPLATES

       STATICFILES_DIRS=(
            os.path.join(BASE_DIR,"statics"),
        )

       STATIC_URL = '/static/' 
       #  我们只能用 STATIC_URL,但STATIC_URL会按着你的STATICFILES_DIRS去找#4  根据需求设计代码
           url.py
           view.py

    #5  使用模版
       render(req,"index.html")   

    #6  启动项目
       python manage.py runserver  127.0.0.1:8090

    #7  连接数据库,操作数据
       model.py

View Code

贰.一.三 U中华VLconf 在怎么着上研究

U帕杰罗Lconf 在呼吁的U奥迪Q五L 上探究,将它看作叁个家常便饭的Python 字符串。不包蕴GET和POST参数以及域名。

例如, 请求中,URLconf 将查找myapp/

在 请求中,U奥德赛Lconf 仍将寻觅myapp/

U奥德赛Lconf 不反省请求的点子。换句话讲,全数的央浼方法 —— 同三个U科雷傲L的POSTGETHEAD等等 —— 都将路由到同一的函数。

django的命令行工具

django-admin.py 是Django的2个用以管理职务的命令行工具,manage.py是对django-admin.py的粗略包装,每个Django Project里都会有1个mannage.py。

<一> 成立一个django工程 : django-admin.py startproject mysite

        当前目录下会生成mysite的工程,目录结构如下:

        www.weide1946.com 78

  • manage.py ----- Django项目里面包车型地铁工具,通过它能够调用django shell和数据库等。
  • settings.py ---- 包蕴了花色的默许设置,包涵数据库新闻,调节和测试标记以及此外一些干活的变量。
  • urls.py ----- 负担把ULX570L情势映射到应用程序。

<贰>在mysite目录下创建blog应用: python manage.py startapp blog

        www.weide1946.com 79

<3>启动django项目:python manage.py runserver 8080

       那样大家的django就运转起来了!当大家走访:

       www.weide1946.com 80

<肆>生成同步数据库的台本:python manage.py makemigrations  

                     同步数据库:  python manage.py migrate   

       注意:在开荒进度中,数据库同步误操作之后,难免会遇到前边不可能共同成功的景况,消除这几个标题标八个轻松易行残酷方法是把migrations目录下

                的脚本(除__init__.py之外)全体删掉,再把数据库删掉之后成立一个新的数据库,数据库同步操作再重复做贰回。            

<伍>当大家访问

       www.weide1946.com 81

       所以大家须求为进入那几个类型的后台创制一级助理馆员:python manage.py createsuperuser安装好用户名和密码后便可记名啦!

<陆>清空数据库:python manage.py  flush

<7>查询某些命令的详细新闻: django-admin.py  help  startapp

       admin 是Django 自带的2个后台数据库管理体系。

<八>运转交互分界面 :python manage.py  shell

     那些命令和平素运转 python 进入 shell 的界别是:你能够在那一个 shell 里面调用当前项目标 models.py 中的 API,对于操作数据,还有局地小测试相当便于。

<9> 极限上输入python manage.py 能够见到详细的列表,在忘记子名称的时候特意有用

二.1.四 捕获的参数永恒是字符串

每一种捕获的参数都看成一个常常的Python 字符串传递给视图,无论正则表明式使用的是怎样相称情势。例如,下边这行UEscortLconf 中:

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

views.year_archive() 的year 参数将是二个字符串

实例练习一-提交数据并展现

www.weide1946.com 82www.weide1946.com 83

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>创建个人信息</h1>

<form action="/userInfor/" method="post">

    <p>姓名<input type="text" name="username"></p>
    <p>性别<input type="text" name="sex"></p>
    <p>邮箱<input type="text" name="email"></p>
    <p><input type="submit" value="submit"></p>

</form>

<hr>

<h1>信息展示</h1>

<table border="1">

    <tr>
        <td>姓名</td>
        <td>性别</td>
        <td>邮箱</td>
    </tr>
    {% for i in info_list %}

        <tr>
            <td>{{ i.username }}</td>
            <td>{{ i.sex }}</td>
            <td>{{ i.email }}</td>
        </tr>

    {% endfor %}

</table>

</body>
</html>


-----------------------url.py---------------------------------------
url(r'^userInfor/', views.userInfor)

-----------------------views.py--------------------------------------

info_list=[]

def userInfor(req):

    if req.method=="POST":
        username=req.POST.get("username",None)
        sex=req.POST.get("sex",None)
        email=req.POST.get("email",None)

        info={"username":username,"sex":sex,"email":email}
        info_list.append(info)

    return render(req,"userInfor.html",{"info_list":info_list})

View Code

二.一.⑤ 钦赐视图参数的默许值

有2个方便的小才干是钦赐视图参数的默许值。 下边是一个U景逸SUVLconf 和视图的以身作则:

www.weide1946.com 84

# 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"):

    ...

www.weide1946.com 85

在位置的事例中,多少个U福特ExplorerL方式指向同三个视图views.page —— 然则首先个情势不会从URAV四L 中捕获任何值。假设第1个方式相配,page() 函数将接纳num参数的默许值"一"。假如第3个形式相称,page() 将使用正则表达式捕获的num 值。

实例练习贰-交给数据并出示(数据库)

www.weide1946.com 86www.weide1946.com 87

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>创建个人信息</h1>

<form action="/userInfor/" method="post">

    <p>姓名<input type="text" name="username"></p>
    <p>性别<input type="text" name="sex"></p>
    <p>邮箱<input type="text" name="email"></p>
    <p><input type="submit" value="submit"></p>

</form>

<hr>

<h1>信息展示</h1>

<table border="1">

    <tr>
        <td>姓名</td>
        <td>性别</td>
        <td>邮箱</td>
    </tr>
    {% for i in info_list %}

        <tr>
            <td>{{ i.username }}</td>
            <td>{{ i.sex }}</td>
            <td>{{ i.email }}</td>
        </tr>

    {% endfor %}

</table>

</body>
</html>


----------------------------------------------models.py
from django.db import models

# Create your models here.


class UserInfor(models.Model):

    username=models.CharField(max_length=64)
    sex=models.CharField(max_length=64)
    email=models.CharField(max_length=64)

----------------------------------------------views.py

from django.shortcuts import render

from app01 import models
# Create your views here.


def userInfor(req):

    if req.method=="POST":
        u=req.POST.get("username",None)
        s=req.POST.get("sex",None)
        e=req.POST.get("email",None)


       #---------表中插入数据方式一
            # info={"username":u,"sex":e,"email":e}
            # models.UserInfor.objects.create(**info)

       #---------表中插入数据方式二
        models.UserInfor.objects.create(
            username=u,
            sex=s,
            email=e
        )

        info_list=models.UserInfor.objects.all()

        return render(req,"userInfor.html",{"info_list":info_list})

    return render(req,"userInfor.html")

View Code

2.1.6 Including other URLconfs

www.weide1946.com 88

#At any point, your urlpatterns can “include” other URLconf modules. This
#essentially “roots” a set of URLs below other ones.

#For example, here’s an excerpt of the URLconf for the Django website itself.
#It includes a number of other URLconfs:


from django.conf.urls import include, url

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

www.weide1946.com 89

四 Django的配备文件(settings)

贰.二 传递额外的选项给视图函数(精通)

UCR-VLconfs 具备2个钩子,令你传递三个Python 字典作为额外的参数字传送递给视图函数。

django.conf.urls.url() 函数能够选取一个可选的第四个参数,它是1个字典,表示想要传递给视图函数的附加关键字参数。

例如:

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

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

在那一个事例中,对于/blog/2005/请求,Django 将调用views.year_archive(request, year='2005', foo='bar')

那个技巧在Syndication 框架中应用,来传递元数据和甄选给视图。

静态文件设置:

www.weide1946.com 90www.weide1946.com 91

一、概述:

     #静态文件交由Web服务器处理,Django本身不处理静态文件。简单的处理逻辑如下(以nginx为例):

     #          URI请求-----> 按照Web服务器里面的配置规则先处理,以nginx为例,主要求配置在nginx.
                             #conf里的location

                         |---------->如果是静态文件,则由nginx直接处理

                         |---------->如果不是则交由Django处理,Django根据urls.py里面的规则进行匹配

    # 以上是部署到Web服务器后的处理方式,为了便于开发,Django提供了在开发环境的对静态文件的处理机制,方法是这样:

    #1、在INSTALLED_APPS里面加入'django.contrib.staticfiles',

    #2、在urls.py里面加入
       if settings.DEBUG:  
           urlpatterns  = patterns('', url(r'^media/(?P<path>.*)$', 
           'django.views.static.serve', {'document_root': settings.MEDIA_ROOT }),   
            url(r'^static/(?P<path>.*)$',
          'django.views.static.serve',{'document_root':settings.STATIC_ROOT}), )  

    # 3、这样就可以在开发阶段直接使用静态文件了。

二、MEDIA_ROOT和MEDIA_URL

        #而静态文件的处理又包括STATIC和MEDIA两类,这往往容易混淆,在Django里面是这样定义的:

        #MEDIA:指用户上传的文件,比如在Model里面的FileFIeld,ImageField上传的文件。如果你定义

        #MEDIA_ROOT=c:tempmedia,那么File=models.FileField(upload_to="abc/")#,上传的文件就会被保存到c:tempmediaabc  
        #eg:
            class blog(models.Model):  
                   Title=models.charField(max_length=64)  
                   Photo=models.ImageField(upload_to="photo") 
        #     上传的图片就上传到c:tempmediaphoto,而在模板中要显示该文件,则在这样写
        #在settings里面设置的MEDIA_ROOT必须是本地路径的绝对路径,一般是这样写:
                 BASE_DIR= os.path.abspath(os.path.dirname(__file__))  
                 MEDIA_ROOT=os.path.join(BASE_DIR,'media/').replace('\','/') 

        #MEDIA_URL是指从浏览器访问时的地址前缀,举个例子:
            MEDIA_ROOT=c:tempmediaphoto  
            MEDIA_URL="/data/"
        #在开发阶段,media的处理由django处理:

        #    访问http://localhost/data/abc/a.png就是访问c:tempmediaphotoabca.png

        #    在模板里面这样写<img src="{{MEDIA_URL}}abc/a.png">

        #    在部署阶段最大的不同在于你必须让web服务器来处理media文件,因此你必须在web服务器中配置,
        #  以便能让web服务器能访问media文件
        #    以nginx为例,可以在nginx.conf里面这样:

                 location ~/media/{
                       root/temp/
                       break;
                    }

        #    具体可以参考如何在nginx部署django的资料。

三、STATIC_ROOT和STATIC_URL、
    STATIC主要指的是如css,js,images这样文件,在settings里面可以配置STATIC_ROOT和STATIC_URL,
    配置方式与MEDIA_ROOT是一样的,但是要注意

    #STATIC文件一般保存在以下位置:

    #1、STATIC_ROOT:在settings里面设置,一般用来放一些公共的js,css,images等。

    #2、app的static文件夹,在每个app所在文夹均可以建立一个static文件夹,然后当运行collectstatic时,
    #    Django会遍历INSTALL_APPS里面所有app的static文件夹,将里面所有的文件复制到STATIC_ROOT。因此,
    #   如果你要建立可复用的app,那么你要将该app所需要的静态文件放在static文件夹中。

    # 也就是说一个项目引用了很多app,那么这个项目所需要的css,images等静态文件是分散在各个app的static文件的,比
    #  较典型的是admin应用。当你要发布时,需要将这些分散的static文件收集到一个地方就是STATIC_ROOT。

    #3、STATIC文件还可以配置STATICFILES_DIRS,指定额外的静态文件存储位置。
    #  STATIC_URL的含义与MEDIA_URL类似。

    # ----------------------------------------------------------------------------
    #注意1:
        #为了后端的更改不会影响前端的引入,避免造成前端大量修改

        STATIC_URL = '/static/'               #引用名
        STATICFILES_DIRS = (
            os.path.join(BASE_DIR,"statics")  #实际名 ,即实际文件夹的名字
        )

        #django对引用名和实际名进行映射,引用时,只能按照引用名来,不能按实际名去找
        #<script src="/statics/jquery-3.1.1.js"></script>
        #------error-----不能直接用,必须用STATIC_URL = '/static/':
        #<script src="/static/jquery-3.1.1.js"></script>

    #注意2(statics文件夹写在不同的app下,静态文件的调用):

        STATIC_URL = '/static/'

        STATICFILES_DIRS=(
            ('hello',os.path.join(BASE_DIR,"app01","statics")) ,
        )

        #<script src="/static/hello/jquery-1.8.2.min.js"></script>

    #注意3:
        STATIC_URL = '/static/'
        {% load staticfiles %}
       # <script src={% static "jquery-1.8.2.min.js" %}></script>

View Code

2.3 name参数

www.weide1946.com 92www.weide1946.com 93

urlpatterns = [
    url(r'^index',views.index,name='INDEX'),

]
###################

def index(req):
    if req.method=='POST':
        username=req.POST.get('username')
        password=req.POST.get('password')
        if username=='alex' and password=='123':
            return HttpResponse("登陆成功")

    return render(req,'index.html')

#####################

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{#     <form action="/index/" method="post">#}
     <form action="{% url 'INDEX' %}" method="post">
         用户名:<input type="text" name="username">
         密码:<input type="password" name="password">
         <input type="submit" value="submit">
     </form>
</body>
</html>


#######################

'''
复制代码

View Code

 

3 编写视图

2个视图函数,或然简单来说叫做视图,是三个简易的Python函数,它接受web请求,并且重临web响应。响应得以是一张网页的HTML内容,3个重定向,几个40四错误,贰个XML文书档案,也许一张图片. . . 是别的东西都得以。无论视图本人包涵怎样逻辑,都要赶回响应。代码写在哪里也不在乎,只要它在你的Python目录上边。除了那几个之外未有更加多的渴求了——能够说“没有何样神奇的地点”。为了能够把代码放在有个别地方,惯例是把视图放在叫做views.py的公文中,然后把它放到你的项目恐怕使用目录里。

任何重要参数设置:

APPEND_SLASH
       Default: True
       When set to True, if the request URL does not match any of the patterns in the URLconf and it 
       doesn’t end in a slash, an HTTP redirect is issued to the same URL with a slash appended. Note 
       that the redirect may cause any data submitted in a POST request to be lost.

3.1 三个简约的视图

下边是二个回到当今日期和时间作为HTML文书档案的视图:

www.weide1946.com 94

from django.http import HttpResponse
import datetime

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

www.weide1946.com 95

让大家逐行阅读方面包车型大巴代码:

  • 先是,我们从 django.http模块导入了HttpResponse类,以及Python的datetime库。
  • 接着,大家定义了current_datetime函数。它是叁个视图函数。每一个视图函数都应抽取HttpRequest对象作为第1个参数,一般叫做request。
  • 在意视图函数的称谓并不根本;无需用五个会集的命名形式来命名,以便让Django识别它。我们将其取名叫current_datetime,是因为那一个名号能够正确地反映出它的效果。
  • 本条视图会再次来到三个HttpResponse对象,其中蕴涵生成的响应。每种视图函数都要回来HttpResponse对象
'''
http请求-响应过程中有两个核心对象:

        http请求对象:HttpRequest

        http响应响应:HttpResponse

所在位置:django.http

'''

伍 Django UPAJEROL (路由系统)

     U奥迪Q5L配置(ULX570Lconf)就好像Django 所帮助网站的目录。它的敬亭山真面目是UKoleosL形式以及要为该U普拉多L情势调用的视图函数之间的映射表;你便是以那种办法告知Django,对于那几个UCRUISERL调用那段代码,对于这几个U猎豹CS陆L调用那段代码。

urlpatterns = [
    url(正则表达式, views视图函数,参数,别名),
]

参数表明:

  • 3个正则表明式字符串
  • 二个可调用对象,日常为三个视图函数或二个点名视图函数路线的字符串
  • 可选的要传递给视图函数的暗许参数(字典格局)
  • 叁个可选的name参数

三.二  急忙函数

5.1 Here’s a sample URLconf:

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

from app01 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})/$', views.year_archive),  #no_named group

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

]

Note:

www.weide1946.com 96www.weide1946.com 97

#1   There’s no need to add a leading slash, because every URL has that. For
#    example, it’s ^articles, not ^/articles.

#2   A request to /articles/2005/03/ would match the third entry in the list.
#    Django would call the function views.month_archive(request, '2005', '03').

#3   /articles/2005/3/ would not match any URL patterns

#4   /articles/2003/ would match the first pattern in the list, not the second one

#5   /articles/2003/03/03/ would match the final pattern. Django would call the
#    functionviews.article_detail(request, '2003', '03', '03').

View Code

3.2.1 render函数

www.weide1946.com 98

---------------render(request, template_name[, context])

结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。

参数:
     request: 用于生成响应的请求对象。

     template_name:要使用的模板的完整名称,可选的参数

     context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。

     content_type:生成的文档要使用的MIME类型。默认为DEFAULT_CONTENT_TYPE 设置的值。

     status:响应的状态码。默认为200。

www.weide1946.com 99

5.2 Named groups

      The above example used simple, non-named regular-expression groups (via parenthesis) to capture bits of the URL and pass them as positional arguments to a view. In more advanced usage, it’s possible to use named regular-expression groups to capture URL bits and pass them as keyword arguments to a view.

       In Python regular expressions, the syntax for named regular-expression groups is (?P<name>pattern), where name is the name of the group and pattern is some pattern to match.

Here’s the above example URLconf, rewritten to use named groups:

www.weide1946.com 100www.weide1946.com 101

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

ready

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),
]

       This accomplishes exactly the same thing as the previous example, with one subtle difference: The captured values are passed to view functions as keyword arguments rather than positional arguments.

3.2.2 redirect函数

www.weide1946.com 102

-----------------------------------url.py

 url(r"login",   views.login),
 url(r"yuan_back",   views.yuan_back),

-----------------------------------views.py
def login(req):
    if req.method=="POST":
        if 1:
            # return redirect("/yuan_back/")
            name="yuanhao"

            return render(req,"my backend.html",locals())

    return render(req,"login.html",locals())


def yuan_back(req):

    name="苑昊"

    return render(req,"my backend.html",locals())

-----------------------------------login.html

<form action="/login/" method="post">
    <p>姓名<input type="text" name="username"></p>
    <p>性别<input type="text" name="sex"></p>
    <p>邮箱<input type="text" name="email"></p>
    <p><input type="submit" value="submit"></p>
</form>
-----------------------------------my backend.html
<h1>用户{{ name }}你好</h1>

#总结: render和redirect的区别:
#   1 if render的页面需要模板语言渲染,需要的将数据库的数据加载到html,那么所有的这一部分
#     除了写在yuan_back的视图函数中,必须还要写在login中,代码重复,没有解耦.

#   2 the most important: url没有跳转到/yuan_back/,而是还在/login/,所以当刷新后
#     又得重新登录.

www.weide1946.com 103

四 Template

5.3  Passing extra options to view functions

       URLconfs have a hook that lets you pass extra arguments to your view functions, as a Python dictionary.

The django.conf.urls.url() function can take an optional third argument which should be a dictionary of extra keyword arguments to pass to the view function.

For example:

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

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

       In this example, for a request to /blog/2005/, Django will call views.year_archive(request, year='2005',foo='bar').

This technique is used in the syndication framework to pass metadata and options to views.

Dealing with conflicts

       It’s possible to have a URL pattern which captures named keyword arguments, and also passes arguments with the same names in its dictionary of extra arguments. When this happens, the arguments in the dictionary will be used instead of the arguments captured in the URL.

肆.一 模板系统的牵线

你大概已经注意到我们在例子视图中回到文本的方法有点尤其。 也等于说,HTML被直接硬编码在 Python代码之中。

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

尽管那种本事便利解释视图是什么样行事的,但直接将HTML硬编码到你的视图里却并不是三个好主意。 让大家来看一下为啥:

  • 对页面设计实行的别的变动都无法不对 Python 代码实行对应的更改。 站点设计的修改往往比底层 Python 代码的退换要再3得多,因而借使得以在不举行 Python 代码修改的景观下退换规划,那将会方便得多。
  • Python 代码编写和 HTML 设计是两项分歧的干活,大很多专门的学业的网址开采意况都将他们分配给不一样的职员(以致不一样部门)来成功。 设计者和HTML/CSS的编码职员不应有被须求去编辑Python的代码来达成他们的办事。
  • 技术员编写 Python代码和规划职员制作模板两项职业而且拓展的效用是参天的,远胜于让1人静观其变另一位形成对有个别既涵盖 Python又富含 HTML 的文书的编辑职业。

依赖那么些原因,将页面包车型地铁准备和Python的代码分离开会更干净简单更便于保险。 大家能够使用 Django的 模板系统 (Template System)来完结那种格局,那便是本章要切实研究的难题。

python的沙盘:HTML代码+逻辑调节代码

5.4 name param

www.weide1946.com 104www.weide1946.com 105

urlpatterns = [
    url(r'^index',views.index,name='bieming'),
    url(r'^admin/', admin.site.urls),
    # 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),

]
###################

def index(req):
    if req.method=='POST':
        username=req.POST.get('username')
        password=req.POST.get('password')
        if username=='alex' and password=='123':
            return HttpResponse("登陆成功")



    return render(req,'index.html')

#####################

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{#     <form action="/index/" method="post">#}
     <form action="{% url 'bieming' %}" method="post">
         用户名:<input type="text" name="username">
         密码:<input type="password" name="password">
         <input type="submit" value="submit">
     </form>
</body>
</html>


#######################

View Code

4.二 模板帮助的语法

5.5 Including other URLconfs

#At any point, your urlpatterns can “include” other URLconf modules. This
#essentially “roots” a set of URLs below other ones.

#For example, here’s an excerpt of the URLconf for the Django website itself.
#It includes a number of other URLconfs:


from django.conf.urls import include, url

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

4.二.一  变量(使用双大括号来引用变量)

语法格式:       {{var_name}}

www.weide1946.com 106

----------------------------------Template和Context对象 
>>> python manange.py shell  (进入该django项目的环境)
>>> from django.template import Context, Template
>>> t = Template('My name is {{ name }}.')
>>> c = Context({'name': 'Stephane'})
>>> t.render(c)
'My name is Stephane.'


# 同一模板,多个上下文,一旦有了模板对象,你就可以通过它渲染多个context,无论何时我们都可以
# 像这样使用同一模板源渲染多个context,只进行 一次模板创建然后多次调用render()方法渲染会
# 更为高效:
# Low
for name in ('John', 'Julie', 'Pat'):
    t = Template('Hello, {{ name }}')
    print t.render(Context({'name': name}))

# Good
t = Template('Hello, {{ name }}')
for name in ('John', 'Julie', 'Pat'):
    print t.render(Context({'name': name}))

www.weide1946.com 107

Django 模板解析十分神速。 大部分的辨析工作都以在后台通过对简易正则表明式二回性调用来成功。 那和依靠 XML 的沙盘引擎变成明显相比,那多少个引擎肩负了 XML 解析器的付出,且频仍比 Django 模板渲染引擎要慢上多少个数据级。

www.weide1946.com 108www.weide1946.com 109

from django.shortcuts import render,HttpResponse
from django.template.loader import get_template #记得导入
# Create your views here.


import datetime
from django.template import Template,Context

# def current_time(req):
    #原始的视图函数
    # now=datetime.datetime.now()
    # html="<html><body>现在时刻:<h1>%s.</h1></body></html>" %now
    # return HttpResponse(html)



# def current_time(req):

      #django模板修改的视图函数
#     now=datetime.datetime.now()
#     t=Template('<html><body>现在时刻是:<h1 style="color:red">{{current_date}}</h1></body></html>')
      #t=get_template('current_datetime.html')
#     c=Context({'current_date':now})
#     html=t.render(c)
#     return HttpResponse(html)

#另一种写法(推荐)

def current_time(req):

    now=datetime.datetime.now()

    return render(req, 'current_datetime.html', {'current_date':now})

View Code

陆 Django Views(视图函数)

www.weide1946.com 110

http请求中生出多少个基本目的:

        http请求:HttpRequest对象

        http响应:HttpResponse对象

所在地方:django.http

前边大家用到的参数request就是HttpRequest    检查评定方法:isinstance(request,HttpRequest)

④.二.贰 深度变量的检索(万能的句点号)

在到近来截止的事例中,大家通过 context 传递的简要参数值主倘诺字符串,不过,模板系统能够充裕简单地拍卖尤其复杂的数据结构,举个例子list、dictionary和自定义的目的。在 Django 模板中遍历复杂数据结构的重视是句点字符 (.)。

www.weide1946.com 111

#最好是用几个例子来说明一下。
# 首先,句点可用于访问列表索引,例如:

>>> from django.template import Template, Context
>>> t = Template('Item 2 is {{ items.2 }}.')
>>> c = Context({'items': ['apples', 'bananas', 'carrots']})
>>> t.render(c)
'Item 2 is carrots.'

#假设你要向模板传递一个 Python 字典。 要通过字典键访问该字典的值,可使用一个句点:
>>> from django.template import Template, Context
>>> person = {'name': 'Sally', 'age': '43'}
>>> t = Template('{{ person.name }} is {{ person.age }} years old.')
>>> c = Context({'person': person})
>>> t.render(c)
'Sally is 43 years old.'

#同样,也可以通过句点来访问对象的属性。 比方说, Python 的 datetime.date 对象有
#year 、 month 和 day 几个属性,你同样可以在模板中使用句点来访问这些属性:

>>> from django.template import Template, Context
>>> import datetime
>>> d = datetime.date(1993, 5, 2)
>>> d.year
1993
>>> d.month
5
>>> d.day
2
>>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
>>> c = Context({'date': d})
>>> t.render(c)
'The month is 5 and the year is 1993.'

# 这个例子使用了一个自定义的类,演示了通过实例变量加一点(dots)来访问它的属性,这个方法适
# 用于任意的对象。
>>> from django.template import Template, Context
>>> class Person(object):
...     def __init__(self, first_name, last_name):
...         self.first_name, self.last_name = first_name, last_name
>>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')
>>> c = Context({'person': Person('John', 'Smith')})
>>> t.render(c)
'Hello, John Smith.'

# 点语法也可以用来引用对象的方法。 例如,每个 Python 字符串都有 upper() 和 isdigit()
# 方法,你在模板中可以使用同样的句点语法来调用它们:
>>> from django.template import Template, Context
>>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')
>>> t.render(Context({'var': 'hello'}))
'hello -- HELLO -- False'
>>> t.render(Context({'var': '123'}))
'123 -- 123 -- True'

# 注意这里调用方法时并* 没有* 使用圆括号 而且也无法给该方法传递参数;你只能调用不需参数的
# 方法。

www.weide1946.com 112

一 HttpRequest对象的属性和格局:

www.weide1946.com 113www.weide1946.com 114

# 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支持时该属性才可用。

#方法
get_full_path(),   比如:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()得到的结果就是/index33/?name=123
req.path:/index33

View Code

4.②.三 变量的过滤器(filter)的利用

语法格式:      {{obj|filter:param}}

www.weide1946.com 115www.weide1946.com 116

复制代码
 # 1  add          :   给变量加上相应的值
   #
   # 2  addslashes   :    给变量中的引号前加上斜线
   #
   # 3  capfirst     :    首字母大写
   #
   # 4  cut          :   从字符串中移除指定的字符
   #
   # 5  date         :   格式化日期字符串
   #
   # 6  default      :   如果值是False,就替换成设置的默认值,否则就是用本来的值
   #
   # 7  default_if_none:  如果值是None,就替换成设置的默认值,否则就使用本来的值


#实例:

#value1="aBcDe"
{{ value1|upper }}<br>

#value2=5
{{ value2|add:3 }}<br>

#value3='he  llo wo r ld'
{{ value3|cut:' ' }}<br>

#import datetime
#value4=datetime.datetime.now()
{{ value4|date:'Y-m-d' }}<br>

#value5=[]
{{ value5|default:'空的' }}<br>

#value6='<a href="#">跳转</a>'

{{ value6 }}

{% autoescape off %}
  {{ value6 }}
{% endautoescape %}

{{ value6|safe }}<br>

{{ value6|striptags }}

#value7='1234'
{{ value7|filesizeformat }}<br>
{{ value7|first }}<br>
{{ value7|length }}<br>
{{ value7|slice:":-1" }}<br>

#value8='http://www.baidu.com/?a=1&b=3'
{{ value8|urlencode }}<br>
    value9='hello I am yuan'

View Code

四.二.4 标签(tag)的施用(使用大括号和比例的3结合来代表使用tag)

语法格式:    {% tags %}

只顾三个常用方法:request.POST.getlist('')

{% if %} 的使用 

{% if %}标签计算一个变量值,如果是“true”,即它存在、不为空并且不是false的boolean值,系统则会显得{% if %}和{% endif %}间的全数内容

www.weide1946.com 117

{% if num >= 100 and 8 %}

    {% if num > 200 %}
        <p>num大于200</p>
    {% else %}
        <p>num大于100小于200</p>
    {% endif %}

{% elif num < 100%}
    <p>num小于100</p>

{% else %}
    <p>num等于100</p>

{% endif %}



{% if %} 标签接受and,or或者not来测试多个变量值或者否定一个给定的变量
{% if %} 标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的:

{% if obj1 and obj2 or obj3 %} 

www.weide1946.com 118

2 HttpResponse对象:

  对于HttpRequest对象的话,是由django自动创设的,然则,HttpResponse对象就不能够不我们和煦创设。各个view请求管理方法必须再次来到二个HttpResponse对象。

  HttpResponse类在django.http.HttpResponse

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

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

补充:

www.weide1946.com 119www.weide1946.com 120

-----------------------------------url.py

 url(r"login",   views.login),
 url(r"yuan_back",   views.yuan_back),

-----------------------------------views.py
def login(req):
    if req.method=="POST":
        if 1:
            # return redirect("/yuan_back/")
            name="yuanhao"

            return render(req,"my backend.html",locals())

    return render(req,"login.html",locals())


def yuan_back(req):

    name="苑昊"

    return render(req,"my backend.html",locals())

-----------------------------------login.html

<form action="/login/" method="post">
    <p>姓名<input type="text" name="username"></p>
    <p>性别<input type="text" name="sex"></p>
    <p>邮箱<input type="text" name="email"></p>
    <p><input type="submit" value="submit"></p>
</form>
-----------------------------------my backend.html
<h1>用户{{ name }}你好</h1>

#总结: render和redirect的区别:
#   1 if render的页面需要模板语言渲染,需要的将数据库的数据加载到html,那么所有的这一部分
#     除了写在yuan_back的视图函数中,必须还要写在login中,代码重复,没有解耦.

#   2 the most important: url没有跳转到/yuan_back/,而是还在/login/,所以当刷新后
#     又得重新登录.

View Code

{% for %}的使用

{% for %}标签允许你按梯次遍历叁个队列中的各样要素,每趟循环模板系统都会渲染{% for %}和{% endfor %}之间的富有内容

www.weide1946.com 121

<ul>
{% for obj in list %}
    <li>{{ obj.name }}</li>
{% endfor %}
</ul>


#在标签里添加reversed来反序循环列表:

    {% for obj in list reversed %}
    ...
    {% endfor %}

#{% for %}标签可以嵌套:

    {% for country in countries %}
        <h1>{{ country.name }}</h1>
        <ul>
         {% for city in country.city_list %}
            <li>{{ city }}</li>
         {% endfor %}
        </ul>
    {% endfor %}


#系统不支持中断循环,系统也不支持continue语句,{% for %}标签内置了一个forloop模板变量,
#这个变量含有一些属性可以提供给你一些关于循环的信息

1,forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1:

    {% for item in todo_list %}
        <p>{{ forloop.counter }}: {{ item }}</p>
    {% endfor %}
2,forloop.counter0 类似于forloop.counter,但它是从0开始计数,第一次循环设为0
3,forloop.revcounter
4,forloop.revcounter0
5,forloop.first当第一次循环时值为True,在特别情况下很有用:


    {% for object in objects %}   
         {% if forloop.first %}<li class="first">{% else %}<li>{% endif %}   
         {{ object }}   
        </li>  
    {% endfor %}  

# 富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了
# 如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它
# Django会在for标签的块中覆盖你定义的forloop变量的值
# 在其他非循环的地方,你的forloop变量仍然可用


#{% empty %}

{{li }}
      {%  for i in li %}
          <li>{{ forloop.counter0 }}----{{ i }}</li>
      {% empty %}
          <li>this is empty!</li>
      {% endfor %}

#         [11, 22, 33, 44, 55]
#            0----11
#            1----22
#            2----33
#            3----44
#            4----55

www.weide1946.com 122

七 Template基础 

csrf_token标签

用来生成csrf_token的价签,用于防治跨站攻击验证。 其实,这里是会调换2个input标签,和其余表单标签一同交给给后台的。

模板系统的牵线

您恐怕早已注意到我们在例子视图中回到文本的办法某个越发。 也等于说,HTML被间接硬编码在 Python代码之中。

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

纵然这种才具便利解释视图是哪些做事的,但一向将HTML硬编码到您的视图里却并不是1个好主意。 让我们来看一下为何:

  • 对页面设计举行的其他退换都必须对 Python 代码举行对应的改换。 站点设计的改换往往比底层 Python 代码的修改要频仍得多,由此只要得以在不开始展览 Python 代码修改的状态下更动规划,那将会有益于得多。
  • Python 代码编写和 HTML 设计是两项分裂的专业,大多数行业内部的网址开垦条件都将她们分配给分歧的人口(以致不相同机关)来完结。 设计者和HTML/CSS的编码人士不应该被供给去编辑Python的代码来成功他们的干活。
  • 程序猿编写 Python代码和统一希图人士制作模板两项工作同时进行的功效是最高的,远胜于让1位拭目以俟另一人完结对有些既包含Python又饱含 HTML 的公文的编纂工作。

听别人说这几个原因,将页面包车型客车企图和Python的代码分离开会更通透到底简洁更便于保险。 大家得以行使 Django的 模板系统 (Template System)来落到实处那种格局,那正是本章要切实可行探讨的标题。

------------------------------------------------------------------模板语法------------------------------------------------------------------

{% url %}

引用路由配置的地址

<form action="{% url "bieming"%}" >
          <input type="text">
          <input type="submit"value="提交">
          {%csrf_token%}
</form>

一模板的结合

组合:HTML代码+逻辑调节代码

{% with %}

用更简明的变量名代替复杂的变量名

{% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}

2 逻辑调节代码的整合

{% verbatim %}

禁止render

{% verbatim %}
         {{ hello }}
{% endverbatim %}

1  变量(使用双大括号来引用变量):

语法格式:       {{var_name}}

------Template和Context对象

www.weide1946.com 123www.weide1946.com 124

>>> python manange.py shell  (进入该django项目的环境)
>>> from django.template import Context, Template
>>> t = Template('My name is {{ name }}.')
>>> c = Context({'name': 'Stephane'})
>>> t.render(c)
'My name is Stephane.'


# 同一模板,多个上下文,一旦有了模板对象,你就可以通过它渲染多个context,无论何时我们都可以
# 像这样使用同一模板源渲染多个context,只进行 一次模板创建然后多次调用render()方法渲染会
# 更为高效:
# Low
for name in ('John', 'Julie', 'Pat'):
    t = Template('Hello, {{ name }}')
    print t.render(Context({'name': name}))

# Good
t = Template('Hello, {{ name }}')
for name in ('John', 'Julie', 'Pat'):
    print t.render(Context({'name': name}))

View Code

 Django 模板解析非凡火速。 超过半数的剖析职业都以在后台通过对简易正则表明式贰次性调用来完结。 那和依附 XML 的沙盘引擎产生鲜明比较,那多少个引擎担当了 XML 解析器的费用,且频仍比 Django 模板渲染引擎要慢上多少个数据级。

www.weide1946.com 125www.weide1946.com 126

from django.shortcuts import render,HttpResponse
from django.template.loader import get_template #记得导入
# Create your views here.


import datetime
from django.template import Template,Context

# def current_time(req):
    #原始的视图函数
    # now=datetime.datetime.now()
    # html="<html><body>现在时刻:<h1>%s.</h1></body></html>" %now
    # return HttpResponse(html)



# def current_time(req):

      #django模板修改的视图函数
#     now=datetime.datetime.now()
#     t=Template('<html><body>现在时刻是:<h1 style="color:red">{{current_date}}</h1></body></html>')
      #t=get_template('current_datetime.html')
#     c=Context({'current_date':now})
#     html=t.render(c)
#     return HttpResponse(html)

#另一种写法(推荐)

def current_time(req):

    now=datetime.datetime.now()

    return render(req, 'current_datetime.html', {'current_date':now})

推荐形式

**------纵深变量的物色(万能的句点号)**

在到近来截至的事例中,大家因而 context 传递的大概参数值首如果字符串,但是,模板系统能够丰裕轻松地管理越发扑朔迷离的数据结构,举例list、dictionary和自定义的对象。

在 Django 模板中遍历复杂数据结构的重大是句点字符 (.)。

www.weide1946.com 127www.weide1946.com 128

#最好是用几个例子来说明一下。
# 首先,句点可用于访问列表索引,例如:

>>> from django.template import Template, Context
>>> t = Template('Item 2 is {{ items.2 }}.')
>>> c = Context({'items': ['apples', 'bananas', 'carrots']})
>>> t.render(c)
'Item 2 is carrots.'

#假设你要向模板传递一个 Python 字典。 要通过字典键访问该字典的值,可使用一个句点:
>>> from django.template import Template, Context
>>> person = {'name': 'Sally', 'age': '43'}
>>> t = Template('{{ person.name }} is {{ person.age }} years old.')
>>> c = Context({'person': person})
>>> t.render(c)
'Sally is 43 years old.'

#同样,也可以通过句点来访问对象的属性。 比方说, Python 的 datetime.date 对象有
#year 、 month 和 day 几个属性,你同样可以在模板中使用句点来访问这些属性:

>>> from django.template import Template, Context
>>> import datetime
>>> d = datetime.date(1993, 5, 2)
>>> d.year
1993
>>> d.month
5
>>> d.day
2
>>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
>>> c = Context({'date': d})
>>> t.render(c)
'The month is 5 and the year is 1993.'

# 这个例子使用了一个自定义的类,演示了通过实例变量加一点(dots)来访问它的属性,这个方法适
# 用于任意的对象。
>>> from django.template import Template, Context
>>> class Person(object):
...     def __init__(self, first_name, last_name):
...         self.first_name, self.last_name = first_name, last_name
>>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')
>>> c = Context({'person': Person('John', 'Smith')})
>>> t.render(c)
'Hello, John Smith.'

# 点语法也可以用来引用对象的方法。 例如,每个 Python 字符串都有 upper() 和 isdigit()
# 方法,你在模板中可以使用同样的句点语法来调用它们:
>>> from django.template import Template, Context
>>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')
>>> t.render(Context({'var': 'hello'}))
'hello -- HELLO -- False'
>>> t.render(Context({'var': '123'}))
'123 -- 123 -- True'

# 注意这里调用方法时并* 没有* 使用圆括号 而且也无法给该方法传递参数;你只能调用不需参数的
# 方法。

View Code

**------变量的过滤器(filter)的施用**

语法格式:      {{obj|filter:param}}

www.weide1946.com 129www.weide1946.com 130

 # 1  add          :   给变量加上相应的值
   #
   # 2  addslashes   :    给变量中的引号前加上斜线
   #
   # 3  capfirst     :    首字母大写
   #
   # 4  cut          :   从字符串中移除指定的字符
   #
   # 5  date         :   格式化日期字符串
   #
   # 6  default      :   如果值是False,就替换成设置的默认值,否则就是用本来的值
   #
   # 7  default_if_none:  如果值是None,就替换成设置的默认值,否则就使用本来的值


#实例:

#value1="aBcDe"
{{ value1|upper }}<br>

#value2=5
{{ value2|add:3 }}<br>

#value3='he  llo wo r ld'
{{ value3|cut:' ' }}<br>

#import datetime
#value4=datetime.datetime.now()
{{ value4|date:'Y-m-d' }}<br>

#value5=[]
{{ value5|default:'空的' }}<br>

#value6='<a href="#">跳转</a>'

{{ value6 }}

{% autoescape off %}
  {{ value6 }}
{% endautoescape %}

{{ value6|safe }}<br>

{{ value6|striptags }}

#value7='1234'
{{ value7|filesizeformat }}<br>
{{ value7|first }}<br>
{{ value7|length }}<br>
{{ value7|slice:":-1" }}<br>

#value8='http://www.baidu.com/?a=1&b=3'
{{ value8|urlencode }}<br>
    value9='hello I am yuan'

View Code

{% load %}

二 标签(tag)的选拔(使用大括号和比例的结缘来表示使用tag)

{% tags %}

**------{% if %} 的使用** 

{% if %}标签总结3个变量值,假使是“true”,即它存在、不为空并且不是false的boolean值,系统则会来得{% if %}和{% endif %}间的装有内容

www.weide1946.com 131www.weide1946.com 132

{% if num >= 100 and 8 %}

    {% if num > 200 %}
        <p>num大于200</p>
    {% else %}
        <p>num大于100小于200</p>
    {% endif %}

{% elif num < 100%}
    <p>num小于100</p>

{% else %}
    <p>num等于100</p>

{% endif %}



{% if %} 标签接受and,or或者not来测试多个变量值或者否定一个给定的变量
{% if %} 标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的:

{% if obj1 and obj2 or obj3 %}  

View Code

**------{% for %}的使用**

{% for %}标签允许你按顺序遍历贰个行列中的各种要素,每趟循环模板系统都会渲染{% for %}和{% endfor %}之间的享有故事情节

www.weide1946.com 133www.weide1946.com 134

<ul>
{% for obj in list %}
    <li>{{ obj.name }}</li>
{% endfor %}
</ul>


#在标签里添加reversed来反序循环列表:

    {% for obj in list reversed %}
    ...
    {% endfor %}

#{% for %}标签可以嵌套:

    {% for country in countries %}
        <h1>{{ country.name }}</h1>
        <ul>
         {% for city in country.city_list %}
            <li>{{ city }}</li>
         {% endfor %}
        </ul>
    {% endfor %}


#系统不支持中断循环,系统也不支持continue语句,{% for %}标签内置了一个forloop模板变量,
#这个变量含有一些属性可以提供给你一些关于循环的信息

1,forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1:

    {% for item in todo_list %}
        <p>{{ forloop.counter }}: {{ item }}</p>
    {% endfor %}
2,forloop.counter0 类似于forloop.counter,但它是从0开始计数,第一次循环设为0
3,forloop.revcounter
4,forloop.revcounter0
5,forloop.first当第一次循环时值为True,在特别情况下很有用:


    {% for object in objects %}   
         {% if forloop.first %}<li class="first">{% else %}<li>{% endif %}   
         {{ object }}   
        </li>  
    {% endfor %}  

# 富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了
# 如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它
# Django会在for标签的块中覆盖你定义的forloop变量的值
# 在其他非循环的地方,你的forloop变量仍然可用


#{% empty %}

{{li }}
      {%  for i in li %}
          <li>{{ forloop.counter0 }}----{{ i }}</li>
      {% empty %}
          <li>this is empty!</li>
      {% endfor %}

#         [11, 22, 33, 44, 55]
#            0----11
#            1----22
#            2----33
#            3----44
#            4----55

View Code

**------{%csrf_token%}:csrf_token标签**

     用于生成csrf_token的标签,用于防治跨站攻击验证。注意假让你在view的index里用的是render_to_response方法,不会收效

     其实,这里是会扭转2个input标签,和任何表单标签一同交给给后台的。

**------{% url %}:  引用路由配置的地址**

www.weide1946.com 135www.weide1946.com 136

<form action="{% url "bieming"%}" >
          <input type="text">
          <input type="submit"value="提交">
          {%csrf_token%}
</form>

View Code

**------{% with %}:用更简明的变量名取代复杂的变量名**

{% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}

**------{% verbatim %}: 禁止render**

{% verbatim %}
         {{ hello }}
{% endverbatim %}

**------{% load %}: 加载标签库
**

加载标签库:自定义filter和simple_tag**

a、在app中创建templatetags模块(必须的)

b、创立放四 .py 文件,如:my_tags.py

www.weide1946.com 137www.weide1946.com 138

from django import template
from django.utils.safestring import mark_safe

register = template.Library()   #register的名字是固定的,不可改变


@register.filter
def filter_multi(v1,v2):
    return  v1 * v2


@register.simple_tag
def simple_tag_multi(v1,v2):
    return  v1 * v2


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

View Code

c、在动用自定义simple_tag和filter的html文件中导入在此之前创立的 my_tags.py :{% load my_tags %}

d、使用simple_tag和filter(如何调用)

-------------------------------.html
{% load xxx %}   #首行


 # num=12
{{ num|filter_multi:2 }} #24

{{ num|filter_multi:"[22,333,4444]" }}


{% simple_tag_multi 2 5 %}  参数不限,但不能放在if for语句中
{% simple_tag_multi num 5 %}

 

e、在settings中的INSTALLED_应用软件S配置当前app,不然django不或许找到自定义的simple_tag.

注意:

filter可以用在if等话语后,simple_tag不可以

{% if num|filter_multi:30 > 100 %}
    {{ num|filter_multi:30 }}
{% endif %}

3 自定义filter和simple_tag**

**------a、在app中创建templatetags模块(必须的)**

**------b、创造任性 .py 文件,如:my_tags.py**

www.weide1946.com 139www.weide1946.com 140

from django import template
from django.utils.safestring import mark_safe

register = template.Library()   #register的名字是固定的,不可改变


@register.filter
def filter_multi(v1,v2):
    return  v1 * v2


@register.simple_tag
def simple_tag_multi(v1,v2):
    return  v1 * v2


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

View Code

**------c、在运用自定义simple_tag和filter的html文件中程导弹入以前创制的 my_tags.py :{% load my_tags %}**

**------d、使用simple_tag和filter(如何调用)**

www.weide1946.com 141www.weide1946.com 142

-------------------------------.html
{% load xxx %}   #首行




 # num=12
{{ num|filter_multi:2 }} #24

{{ num|filter_multi:"[22,333,4444]" }}


{% simple_tag_multi 2 5 %}  参数不限,但不能放在if for语句中
{% simple_tag_multi num 5 %}

View Code

**------e、在settings中的INSTALLED_APPS配置当前app,不然django不恐怕找到自定义的simple_tag.**

注意:

filter能够用在if等说话后,simple_tag不可以

www.weide1946.com 143www.weide1946.com 144

{% if num|filter_multi:30 > 100 %}
    {{ num|filter_multi:30 }}
{% endif %}

View Code

extend模板承袭

到近来结束,大家的沙盘模范都只是些零星的 HTML 片段,但在实际上利用中,你将用 Django 模板系统来创制整个 HTML 页面。 那就推动四个宽广的 Web 开采难题: 在整整网址中,怎么着压缩共用页面区域(举个例子站点导航)所引起的双重和冗余代码?Django 化解此类难题的首荐办法是运用壹种优雅的政策—— 模板承继 。

本质上的话,模板承继正是先构造多个基础框架模板,而后在其子模板中对它所富含站点公用部分和概念块举行重载。

让大家因此修改 current_datetime.html 文件,为 current_datetime 创制一个尤其完整的沙盘来回味一下那种做法:

www.weide1946.com 145

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>The current time</title>
</head>
<body>
    <h1>My helpful timestamp site</h1>
    <p>It is now {{ current_date }}.</p>

    <hr>
    <p>Thanks for visiting my site.</p>
</body>
</html>

www.weide1946.com 146

那看起来很棒,但一旦我们要为 hours_ahead 视图创制另二个模板会发生咋样业务啊?

www.weide1946.com 147

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>Future time</title>
</head>
<body>
    <h1>My helpful timestamp site</h1>
    <p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>

    <hr>
    <p>Thanks for visiting my site.</p>
</body>
</html> 

www.weide1946.com 148

Django 的沙盘承继系统解决了那几个难题。 你能够将其正是服务器端 include 的逆向思维版本。 你能够对那多少个不同 的代码段实行定义,而不是 共同 代码段。

先是步是定义 基础模板,该框架之后将由子模板所承袭。 以下是我们脚下所描述榜样的根底模板:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <h1>My helpful timestamp site</h1>
    {% block content %}{% endblock %}
    {% block footer %}
    <hr>
    <p>Thanks for visiting my site.</p>
    {% endblock %}
</body>
</html>

本条叫做 base.html 的模版定义了一个回顾的 HTML 框架文书档案,大家将在本站点的保有页面中央银行使。 子模板的功效就是重载、增添或保留那多少个块的开始和结果。 (假若您平昔按梯次学习到此处,保存这些文件到你的template目录下,命名称为 base.html .)

咱俩应用模板标签: {% block %} 。 所有的 {% block %} 标签告诉模板引擎,子模板能够重载这一个有个别。 每种{% block %}标签所要做的是告诉模板引擎,该模板下的那一块内容将有非常大只怕被子模板覆盖。

现今我们早已有了二在那之中坚模板,大家得以修改 current_datetime.html 模板来 使用它:

www.weide1946.com 149

{% extends "base.html" %}

{% block title %}The current time{% endblock %}

{% block content %}
<p>It is now {{ current_date }}.</p>
{% endblock %}

www.weide1946.com 150

再为 hours_ahead 视图成立三个模板,看起来是如此的:

www.weide1946.com 151

{% extends "base.html" %}

{% block title %}Future time{% endblock %}

{% block content %}
<p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>
{% endblock %}

www.weide1946.com 152

看起来相当漂亮是或不是? 每一种模板只含有对团结来讲 旷世 的代码。 不须求多余的有的。 假设想举行站点级的宏图修改,仅需修改 base.html ,全部别的模板会应声反映出所作修改。

以下是其专门的工作章程:

      在加载 current_datetime.html 模板时,模板引擎开掘了 {% extends %} 标签, 注意到该模板是二个子模板。 模板引擎顿服饰载其父模板,即本例中的 base.html 。此时,模板引擎注意到 base.html 中的八个 {% block %} 标签,并用子模板的开始和结果替换这些block 。由此,引擎将会采取我们在 { block title %} 中定义的标题,对 {% block content %} 也是那般。 所以,网页标题一块将由{% block title %}轮换,同样地,网页的源委一块将由 {% block content %}替换。

     注意由于子模板并不曾定义 footer 块,模板系统将选用在父模板中定义的值。 父模板 {% block %} 标签中的内容总是被当作一条退路。继承并不会影响到模板的上下文。 换句话说,任何处在承袭树上的模版都能够访问到你传到模板中的每三个模板变量。你能够依靠要求选择放肆多的持续次数。 使用持续的1种常见方式是上面包车型客车三层法:

   <1> 创建 base.html 模板,在其中定义站点的主要外观感受。 这些都是不常修改甚至从不修改的部分。
   <2> 为网站的每个区域创建 base_SECTION.html 模板(例如, base_photos.html 和 base_forum.html )。这些模板对base.html 进行拓展,
       并包含区域特定的风格与设计。
   <3> 为每种类型的页面创建独立的模板,例如论坛页面或者图片库。 这些模板拓展相应的区域模板。

这几个主意可最大限度地引用代码,并使得向国有区域(如区域级的领航)加多内容成为壹件轻便的干活。

以下是选用模板承继的有的妙方:

www.weide1946.com 153

 <1>如果在模板中使用 {% extends %} ,必须保证其为模板中的第一个模板标记。 否则,模板继承将不起作用。

 <2>一般来说,基础模板中的 {% block %} 标签越多越好。 记住,子模板不必定义父模板中所有的代码块,因此
    你可以用合理的缺省值对一些代码块进行填充,然后只对子模板所需的代码块进行(重)定义。 俗话说,钩子越
    多越好。

 <3>如果发觉自己在多个模板之间拷贝代码,你应该考虑将该代码段放置到父模板的某个 {% block %} 中。
    如果你需要访问父模板中的块的内容,使用 {{ block.super }}这个标签吧,这一个魔法变量将会表现出父模
    板中的内容。 如果只想在上级代码块基础上添加内容,而不是全部重载,该变量就显得非常有用了。

 <4>不允许在同一个模板中定义多个同名的 {% block %} 。 存在这样的限制是因为block 标签的工作方式是双向的。
    也就是说,block 标签不仅挖了一个要填的坑,也定义了在父模板中这个坑所填充的内容。如果模板中出现了两个
    相同名称的 {% block %} 标签,父模板将无从得知要使用哪个块的内容。

www.weide1946.com 154

5 数据库与O奥迪Q5M

4 extend模板承袭**

------include 模板标签

在教学了模版加运载飞机制之后,大家再介绍3个选用该机制的内建立模型板标签: {% include %} 。该标签允许在(模板中)包蕴别的的沙盘的剧情。 标签的参数是所要包罗的模版名称,能够是多少个变量,也能够是用单/双引号硬编码的字符串。 每当在四个模板中冒出同等的代码时,就活该思虑是还是不是要采用 {% include %} 来减少重复。

------extend(承继)模板标签

到最近结束,大家的模版范例都只是些零星的 HTML 片段,但在其实使用中,你将用 Django 模板系统来创立整个 HTML 页面。 那就带动3个宽广的 Web 开垦难点: 在全方位网址中,如何减中国少年共产党用页面区域(比如站点导航)所引起的再度和冗余代码?

消除该难题的历史观做法是选择 劳务器端的 includes ,你可以在 HTML 页面中运用该指令将三个网页嵌入到另五个中。 事实上, Django 通过刚才描述的 {% include %} 支持了那种格局。 可是用 Django 解决此类主题材料的首荐办法是采纳进一步高雅的计划—— 模板承继 。

实质上来讲,模板承接就是先构造三个基础框架模板,而后在其子模板中对它所蕴藏站点公用部分和定义块进行重载。

让大家经过改换 current_datetime.html 文件,为 current_datetime 创造3个尤为完整的模板来回味一下那种做法:

www.weide1946.com 155www.weide1946.com 156

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>The current time</title>
</head>
<body>
    <h1>My helpful timestamp site</h1>
    <p>It is now {{ current_date }}.</p>

    <hr>
    <p>Thanks for visiting my site.</p>
</body>
</html>

View Code

那看起来很棒,但如若大家要为 hours_ahead 视图创制另一个模板会时有发生什么职业吗?

www.weide1946.com 157www.weide1946.com 158

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>Future time</title>
</head>
<body>
    <h1>My helpful timestamp site</h1>
    <p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>

    <hr>
    <p>Thanks for visiting my site.</p>
</body>
</html>  

View Code

很显著,大家刚刚重复了汪洋的 HTML 代码。 想象一下,如若有一个更独立的网址,它有导航条、样式表,可能还有局地JavaScript 代码,事情必然以向每种模板填充各个冗余的 HTML 而停止。

消除那些标题的服务器端 include 方案是寻觅多少个模板中的共同部分,将其保存为区别的模板片段,然后在各种模板中开始展览include。 大概你会把模版尾部的一对代码保存为 header.html 文件:

www.weide1946.com 159www.weide1946.com 160

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>

View Code

您大概会把后面部分保存到文件 footer.html :

www.weide1946.com 161www.weide1946.com 162

<hr>
    <p>Thanks for visiting my site.</p>
</body>
</html>

View Code

对基于 include 的计策,底部和尾巴部分的隐含很简短。 麻烦的是高级中学级部分。 在此表率中,各类页面都有八个<h1>My helpful timestamp site</h1> 标题,可是那几个标题不可能放在 header.html 中,因为种种页面包车型客车 <title> 是差异的。 若是大家将 <h1> 包罗在头顶,大家就只能包蕴 <title> ,但那样又不允许在各样页面对它进行定制。 何去何从呢?

Django 的沙盘承继系统消除了那个难题。 你可以将其视为服务器端 include 的逆向思维版本。 你可以对这么些不同 的代码段举办定义,而不是 共同 代码段。

首先步是定义 基础模板,该框架之后将由子模板所承袭。 以下是我们目前所讲述模范的基本功臣楷模板:

www.weide1946.com 163www.weide1946.com 164

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <h1>My helpful timestamp site</h1>
    {% block content %}{% endblock %}
    {% block footer %}
    <hr>
    <p>Thanks for visiting my site.</p>
    {% endblock %}
</body>
</html>

View Code

这么些叫做 base.html 的模版定义了叁个简练的 HTML 框架文书档案,大家就要本站点的有着页面中利用。 子模板的效用便是重载、增添或保留那个块的原委。 (假设您直接按顺序学习到这里,保存这么些文件到您的template目录下,命名字为 base.html .)

大家运用模板标签: {% block %} 。 所有的 {% block %} 标签告诉模板引擎,子模板能够重载那些有个别。 每种{% block %}标签所要做的是告诉模板引擎,该模板下的那1块内容将有希望被子模板覆盖。

今昔我们早就有了3当中央模板,我们得以修改 current_datetime.html 模板来 使用它:

www.weide1946.com 165www.weide1946.com 166

{% extends "base.html" %}

{% block title %}The current time{% endblock %}

{% block content %}
<p>It is now {{ current_date }}.</p>
{% endblock %}

View Code

再为 hours_ahead 视图创制一个模板,看起来是那般的:

www.weide1946.com 167www.weide1946.com 168

{% extends "base.html" %}

{% block title %}Future time{% endblock %}

{% block content %}
<p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>
{% endblock %}

View Code

看起来极美观是或不是? 每一种模板只蕴涵对团结来说 绝世 的代码。 没有供给多余的1对。 假使想拓展站点级的陈设修改,仅需修改 base.html ,全数其余模板会即时反映出所作修改。

      以下是其行事方法:

      在加载 current_datetime.html 模板时,模板引擎发掘了 {% extends %} 标签, 注意到该模板是二个子模板。 模板引擎立衣裳载其父模板,即本例中的 base.html 。此时,模板引擎注意到 base.html 中的三个 {% block %} 标签,并用子模板的剧情替换那几个block 。因而,引擎将会选用大家在 { block title %} 中定义的题目,对 {% block content %} 也是那般。 所以,网页题目1块将由{% block title %}轮换,同样地,网页的剧情一块将由 {% block content %}替换。

     注意由于子模板并未定义 footer 块,模板系统将动用在父模板中定义的值。 父模板 {% block %} 标签中的内容总是被看做一条退路。承接并不会影响到模板的上下文。 换句话说,任何处在承接树上的沙盘都足以访问到你传到模板中的每贰个模板变量。你能够凭仗要求动用大肆多的一连次数。 使用持续的一种常见方式是上面包车型地铁三层法:

   <1> 创建 base.html 模板,在其中定义站点的主要外观感受。 这些都是不常修改甚至从不修改的部分。
   <2> 为网站的每个区域创建 base_SECTION.html 模板(例如, base_photos.html 和 base_forum.html )。这些模板对base.html 进行拓展,
       并包含区域特定的风格与设计。
   <3> 为每种类型的页面创建独立的模板,例如论坛页面或者图片库。 这些模板拓展相应的区域模板。

      那一个方法可最大限度地选拔代码,并使得向国有区域(如区域级的领航)增添内容成为一件轻便的做事。

以下是选取模板承袭的①对路子:

www.weide1946.com 169www.weide1946.com 170

<1>如果在模板中使用 {% extends %} ,必须保证其为模板中的第一个模板标记。 否则,模板继承将不起作用。

 <2>一般来说,基础模板中的 {% block %} 标签越多越好。 记住,子模板不必定义父模板中所有的代码块,因此
    你可以用合理的缺省值对一些代码块进行填充,然后只对子模板所需的代码块进行(重)定义。 俗话说,钩子越
    多越好。

 <3>如果发觉自己在多个模板之间拷贝代码,你应该考虑将该代码段放置到父模板的某个 {% block %} 中。
    如果你需要访问父模板中的块的内容,使用 {{ block.super }}这个标签吧,这一个魔法变量将会表现出父模
    板中的内容。 如果只想在上级代码块基础上添加内容,而不是全部重载,该变量就显得非常有用了。

 <4>不允许在同一个模板中定义多个同名的 {% block %} 。 存在这样的限制是因为block 标签的工作方式是双向的。
    也就是说,block 标签不仅挖了一个要填的坑,也定义了在父模板中这个坑所填充的内容。如果模板中出现了两个
    相同名称的 {% block %} 标签,父模板将无从得知要使用哪个块的内容。

View Code

伍.一 数据库的计划

八 Models

一    django暗中同意援助sqlite,mysql, oracle,postgresql数据库。

     <1> sqlite

            django暗中认可使用sqlite的数据库,暗许自带sqlite的数据库驱动 , 引擎名称:django.db.backends.sqlite三

     <2> mysql

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

数据库的配备

2    mysql驱动程序

  •    MySQLdb(mysql python)
  •    mysqlclient
  •    MySQL
  •    PyMySQL(纯python的mysql驱动程序)

一    django私下认可帮忙sqlite,mysql, oracle,postgresql数据库。

     <1> sqlite

            django暗许使用sqlite的数据库,默许自带sqlite的数据库驱动 , 引擎名称:django.db.backends.sqlite3

     <2> mysql

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

叁     在django的项目中会暗中同意使用sqlite数据库,在settings里有如下设置:

       www.weide1946.com 171    

如若我们想要改换数据库,供给修改如下:

        www.weide1946.com 172 

DATABASES = {

    'default': {

        'ENGINE': 'django.db.backends.mysql', 

        'NAME': 'books',    #你的数据库名称

        'USER': 'root',   #你的数据库用户名

        'PASSWORD': '', #你的数据库密码

        'HOST': '', #你的数据库主机,留空默认为localhost

        'PORT': '3306', #你的数据库端口

    }

}

注意:

www.weide1946.com 173www.weide1946.com 174

复制代码
NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建

USER和PASSWORD分别是数据库的用户名和密码。

设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。

然后,启动项目,会报错:no module named MySQLdb

这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb对于py3有很大问题,所以我们需要的驱动是PyMySQL

所以,我们只需要找到项目名文件下的__init__,在里面写入:

import pymysql
pymysql.install_as_MySQLdb()

问题解决!

View Code

 

5.2  ORM表模型

贰    mysql驱动程序

  •    MySQLdb(mysql python)
  •    mysqlclient
  •    MySQL
  •    PyMySQL(纯python的mysql驱动程序)

表(模型)的创建:

实例:大家来假使上边那么些概念,字段和关系

笔者模型:二个作者有真名。

小编详细模型:把笔者的详细情况放到实际情况表,包罗性别,email地址和出生日期,小编详细的情况模型和笔者模型之间是一定的关系(one-to-one)(类似于每一个人和他的身份证之间的涉及),在诸多意况下我们从不供给将她们拆分成两张表,这里只是引出一对一的定义。

出版商模型:出版商有名称,地址,所在城市,省,国家和网址。

图书模型:书籍有书名和出版日期,壹本书恐怕会有四个小编,八个作者也得以写多本书,所以小编和图书的关系正是多对多的关系关系(many-to-many),1本书只应该由3个出版商出版,所以出版商和书籍是一对多涉及关系(one-to-many),也被称作外键。

www.weide1946.com 175www.weide1946.com 176

from django.db import models<br>
class Publisher(models.Model):
    name = models.CharField(max_length=30, verbose_name="名称")
    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 Meta:
        verbose_name = '出版商'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=30)
    def __str__(self):
        return self.name

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

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()
    price=models.DecimalField(max_digits=5,decimal_places=2,default=10)
    def __str__(self):
        return self.title

View Code

分析代码:

       <1>  每一个数据模型都以django.db.models.Model的子类,它的父类Model包涵了装有须要的和数据库交互的法子。并提供了3个简要介绍美观的定义数据库字段的语法。

       <二>  每一种模型也就是单个数据库表(多对多关系不相同,会多生成一张关系表),各样属性也是以此表中的字段。属性名正是字段名,它的系列(举个例子CharField)约等于数据库的字段类型(例如varchar)。我们能够小心下别的的品类都和数据Curry的什么字段对应。

       <3>  模型之间的两种关系:一对一,1对多,多对多。

             1对一:实质正是在主外键(author_id正是foreign key)的关系基础上,给外键加了3个UNIQUE=True的性质;

             壹对多:正是主外键关系;(foreign key)

             多对多:(ManyToManyField) 自动创造第二张表(当然大家也足以本身创设第2张表:多个foreign key)

三     在django的种类中会暗许使用sqlite数据库,在settings里有如下设置:

       www.weide1946.com 177    

若是我们想要改变数据库,供给修改如下:

        www.weide1946.com 178   

www.weide1946.com 179www.weide1946.com 180

DATABASES = {

    'default': {

        'ENGINE': 'django.db.backends.mysql', 

        'NAME': 'books',    #你的数据库名称

        'USER': 'root',   #你的数据库用户名

        'PASSWORD': '', #你的数据库密码

        'HOST': '', #你的数据库主机,留空默认为localhost

        'PORT': '3306', #你的数据库端口

    }

}

View Code

注意:

www.weide1946.com 181www.weide1946.com 182

NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建

USER和PASSWORD分别是数据库的用户名和密码。

设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。

然后,启动项目,会报错:no module named MySQLdb

这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb对于py3有很大问题,所以我们需要的驱动是PyMySQL

所以,我们只需要找到项目名文件下的__init__,在里面写入:

import pymysql
pymysql.install_as_MySQLdb()

问题解决!

View Code

ORM之增(create,save) 

www.weide1946.com 183

from app01.models import *

    #create方式一:   Author.objects.create(name='Alvin')

    #create方式二:   Author.objects.create(**{"name":"alex"})

    #save方式一:     author=Author(name="alvin")
                            author.save()

    #save方式二:     author=Author()
                            author.name="alvin"
                            author.save()

www.weide1946.com 184

**重中之重来了------->**那正是说如何成立存在1对多或多对多涉及的1本书的新闻呢?(怎么着管理外键关系的字段如一对多的``publisher和多对多的authors)

www.weide1946.com 185 View Code

O奥迪Q五M(对象关联映射)

用于得以完成面向对象编程语言里不相同品种系统的多寡里面包车型大巴转移,换言之,正是用面向对象的主意去操作数据库的创设表以及增加和删除改查等操作。

优点: 一O奥迪Q5M使得大家的通用数据库交互变得简单易行,而且完全不用思虑该死的SQL语句。飞速支付,因而而来。

          2 得以制止有个别新手技术员写sql语句带来的质量难题。

            比如 大家查询User表中的全数字段:

            www.weide1946.com 186

            新手只怕会用select * from  auth_user,这样会因为多了二个金童玉女动作而影响功能的。

 缺点:1  品质有所捐躯,不过以后的种种ORAV肆M框架都在品尝各类法子,比方缓存,延迟加载登来缓和那一个难题。效果很明显。

          2 对此个别复杂查询,O汉兰达M照旧不恐怕,为了化解那一个标题,OXC60M一般也支撑写raw sql。

          3  通过QuerySet的query属性查询相应操作的sql语句

author_obj=models.Author.objects.filter(id=2)
print(author_obj.query)

     上边要早先攻读Django OBMWX3M语法了,为了更加好的通晓,大家来做四个为主的 书籍/小编/出版商 数据库结构。 大家那样做是因为 那是三个眼看的例子,许多SQL有关的书本也常用那一个比喻。

ORM之删(delete)

>>> Book.objects.filter(id=1).delete()
(3, {'app01.Book_authors': 2, 'app01.Book': 1})

咱俩外表上剔除了一条新闻,实际却删除了三条,因为大家删除的那本书在Book_authors表中有两条相关新闻,那种删除情势正是django私下认可的级联删除。

表(模型)的创建:

实例:大家来要是下边那么些概念,字段和事关

作者模型:四个小编有姓名。

小编详细模型:把小编的详细情况放到实际情况表,包涵性别,email地址和出出生之日期,小编详细的情况模型和小编模型之间是非常的关系(one-to-one)(类似于各种人和他的身份证之间的涉嫌),在大部景象下大家平素不供给将他们拆分成两张表,这里只是引出1对1的概念。

出版商模型:出版商盛名称,地址,所在城市,省,国家和网址。

书籍模型:书籍有书名和出版日期,1本书恐怕会有多个笔者,1个我也足以写多本书,所以小编和书本的关联正是多对多的关系关系(many-to-many),1本书只应该由三个出版商出版,所以出版商和本本是一对多涉及关系(one-to-many),也被称作外键。

www.weide1946.com 187www.weide1946.com 188

from django.db import models<br>
class Publisher(models.Model):
    name = models.CharField(max_length=30, verbose_name="名称")
    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 Meta:
        verbose_name = '出版商'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=30)
    def __str__(self):
        return self.name

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

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()
    price=models.DecimalField(max_digits=5,decimal_places=2,default=10)
    def __str__(self):
        return self.title

View Code

注意1:记得在settings里的INSTALLED_APPS中参与'app0壹',然后再一齐数据库。

注意2: models.ForeignKey("Publish") & models.ForeignKey(Publish)

浅析代码:

       <1>  每一种数据模型都以django.db.models.Model的子类,它的父类Model包蕴了颇具须要的和数据库交互的法子。并提供了1个简单介绍美貌的定义数据库字段的语法。

       <2>  每种模型也正是单个数据库表(多对多关系不相同,会多生成一张关系表),各样属性也是这么些表中的字段。属性名正是字段名,它的体系(比如CharField)也正是数据库的字段类型(比如varchar)。大家能够小心下任何的类型都和数据Curry的怎么字段对应。

       <三>  模型之间的二种关系:壹对1,一对多,多对多。

             壹对一:实质便是在主外键(author_id就是foreign key)的涉及基础上,给外键加了叁个UNIQUE=True的性能;

             一对多:就是主外键关系;(foreign key)

             多对多:(ManyToManyField) 自动创设第3张表(当然大家也能够友善创造第一张表:四个foreign key)

       <4>  模型常用的字段类型参数

www.weide1946.com 189www.weide1946.com 190

<1> CharField
        #字符串字段, 用于较短的字符串.
        #CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.

<2> IntegerField
       #用于保存一个整数.

<3> FloatField
        # 一个浮点数. 必须 提供两个参数:
        #
        # 参数    描述
        # max_digits    总位数(不包括小数点和符号)
        # decimal_places    小数位数
                # 举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段:
                #
                # models.FloatField(..., max_digits=5, decimal_places=2)
                # 要保存最大值一百万(小数点后保存10位)的话,你要这样定义:
                #
                # models.FloatField(..., max_digits=19, decimal_places=10)
                # admin 用一个文本框(<input type="text">)表示该字段保存的数据.

<4> AutoField
        # 一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段; 
        # 自定义一个主键:my_id=models.AutoField(primary_key=True)
        # 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.

<5> BooleanField
        # A true/false field. admin 用 checkbox 来表示此类字段.

<6> TextField
        # 一个容量很大的文本字段.
        # admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).

<7> EmailField
        # 一个带有检查Email合法性的 CharField,不接受 maxlength 参数.

<8> DateField
        # 一个日期字段. 共有下列额外的可选参数:
        # Argument    描述
        # auto_now    当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳.
        # auto_now_add    当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.
        #(仅仅在admin中有意义...)

<9> DateTimeField
        #  一个日期时间字段. 类似 DateField 支持同样的附加选项.

<10> ImageField
        # 类似 FileField, 不过要校验上传对象是否是一个合法图片.#它有两个可选参数:height_field和width_field,
        # 如果提供这两个参数,则图片将按提供的高度和宽度规格保存.     
<11> FileField
     # 一个文件上传字段.
     #要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime #formatting, 
     #该格式将被上载文件的 date/time 
     #替换(so that uploaded files don't fill up the given directory).
     # admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) .

     #注意:在一个 model 中使用 FileField 或 ImageField 需要以下步骤:
            #(1)在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件. 
            # (出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对 
            #  WEB服务器用户帐号是可写的.
            #(2) 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django
            # 使用 MEDIA_ROOT 的哪个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT). 
            # 出于习惯你一定很想使用 Django 提供的 get_<#fieldname>_url 函数.举例来说,如果你的 ImageField 
            # 叫作 mug_shot, 你就可以在模板中以 {{ object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径.

<12> URLField
      # 用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且
      # 没有返回404响应).
      # admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)

<13> NullBooleanField
       # 类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项
       # admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes" 和 "No" ) 来表示这种字段数据.

<14> SlugField
       # "Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.#它们通常用于URLs
       # 若你使用 Django 开发版本,你可以指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50.  #在
       # 以前的 Django 版本,没有任何办法改变50 这个长度.
       # 这暗示了 db_index=True.
       # 它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-#populate 
       # the slug, via JavaScript,in the object's admin form: models.SlugField
       # (prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields.

<13> XMLField
        #一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径.

<14> FilePathField
        # 可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的.
        # 参数    描述
        # path    必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目. 
        # Example: "/home/images".
        # match    可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名.  
        # 注意这个正则表达式只会应用到 base filename 而不是
        # 路径全名. Example: "foo.*.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif.
        # recursive可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录.
        # 这三个参数可以同时使用.
        # match 仅应用于 base filename, 而不是路径全名. 那么,这个例子:
        # FilePathField(path="/home/images", match="foo.*", recursive=True)
        # ...会匹配 /homeoo.gif 而不匹配 /homeoo/bar.gif

<15> IPAddressField
        # 一个字符串形式的 IP 地址, (i.e. "24.124.1.30").
<16># CommaSeparatedIntegerField
        # 用于存放逗号分隔的整数值. 类似 CharField, 必须要有maxlength参数.

View Code

       <5>  Field重要参数

www.weide1946.com 191www.weide1946.com 192

    <1> null : 数据库中字段是否可以为空

    <2> blank: django的 Admin 中添加数据时是否可允许空值

    <3> default:设定缺省值

    <4> editable:如果为假,admin模式下将不能改写。缺省为真

    <5> primary_key:设置主键,如果没有设置django创建表时会自动加上:
        id = meta.AutoField('ID', primary_key=True)
        primary_key=True implies blank=False, null=False and unique=True. Only one
        primary key is allowed on an object.

    <6> unique:数据唯一

    <7> verbose_name  Admin中字段的显示名称

    <8> validator_list:有效性检查。非有效产生 django.core.validators.ValidationError 错误


    <9> db_column,db_index 如果为真将为此字段创建索引

    <10>choices:一个用来选择值的2维元组。第一个值是实际存储的值,第二个用来方便进行选择。
                如SEX_CHOICES= (( ‘F’,'Female’),(‘M’,'Male’),)
                gender = models.CharField(max_length=2,choices = SEX_CHOICES)

View Code

ORM之改(update和save)

实例:

    www.weide1946.com 193

注意:

<1> 第几种艺术修改不能用get的缘故是:update是QuerySet对象的办法,get重返的是三个model对象,它从不update方法,而filter重临的是叁个QuerySet对象(filter里面包车型客车基准恐怕有八个条件适合,举例name='alvin',恐怕有四个name='alvin'的行数据)。

<2>在“插入和更新数据”小节中,我们有提到模型的save()方法,这个方法会更新一行里的所有列。 而某些情况下,我们只需要更新行里的某几列。

www.weide1946.com 194 View Code

其它,update()方法对于其余结果集(QuerySet)均有效,这象征你能够而且更新多条记录update()方法会重临二个整型数值,表示受影响的笔录条数。

只顾,这里因为update重返的是二个整形,所以没办法用query属性;对于每便创制2个目的,想体现相应的raw sql,必要在settings加上日志记录部分:

www.weide1946.com 195 View Code

表的操作(增加和删除改查):

**-------------------------------------增(create  ,  save) -------------------------------**

from app01.models import *

    #create方式一:   Author.objects.create(name='Alvin')

    #create方式二:   Author.objects.create(**{"name":"alex"})

    #save方式一:     author=Author(name="alvin")
                    author.save()

    #save方式二:     author=Author()
                    author.name="alvin"
                    author.save()

驷比不上舌来了------->那么怎么着制造存在壹对多或多对多涉及的一本书的音信呢?(怎么样管理外键关系的字段如壹对多的``publisher和多对多的authors)

www.weide1946.com 196www.weide1946.com 197

#一对多(ForeignKey):

    #方式一: 由于绑定一对多的字段,比如publish,存到数据库中的字段名叫publish_id,所以我们可以直接给这个
    #       字段设定对应值:
           Book.objects.create(title='php',
                               publisher_id=2,   #这里的2是指为该book对象绑定了Publisher表中id=2的行对象
                               publication_date='2017-7-7',
                               price=99)


    #方式二:
    #       <1> 先获取要绑定的Publisher对象:
        pub_obj=Publisher(name='河大出版社',address='保定',city='保定',
                state_province='河北',country='China',website='http://www.hbu.com')
    OR  pub_obj=Publisher.objects.get(id=1)

    #       <2>将 publisher_id=2 改为  publisher=pub_obj

#多对多(ManyToManyField()):

    author1=Author.objects.get(id=1)
    author2=Author.objects.filter(name='alvin')[0]
    book=Book.objects.get(id=1)
    book.authors.add(author1,author2)
    #等同于:
    book.authors.add(*[author1,author2])
    book.authors.remove(*[author1,author2])
    #-------------------
    book=models.Book.objects.filter(id__gt=1)
    authors=models.Author.objects.filter(id=1)[0]
    authors.book_set.add(*book)
    authors.book_set.remove(*book)
    #-------------------
    book.authors.add(1)
    book.authors.remove(1)
    authors.book_set.add(1)
    authors.book_set.remove(1)

#注意: 如果第三张表是通过models.ManyToManyField()自动创建的,那么绑定关系只有上面一种方式
#     如果第三张表是自己创建的:
     class Book2Author(models.Model):
            author=models.ForeignKey("Author")
            Book=  models.ForeignKey("Book")
#     那么就还有一种方式:
            author_obj=models.Author.objects.filter(id=2)[0]
            book_obj  =models.Book.objects.filter(id=3)[0]

            s=models.Book2Author.objects.create(author_id=1,Book_id=2)
            s.save()
            s=models.Book2Author(author=author_obj,Book_id=1)
            s.save()

View Code

**-----------------------------------------删(delete) ---------------------------------------------**

>>> Book.objects.filter(id=1).delete()
(3, {'app01.Book_authors': 2, 'app01.Book': 1})

咱俩外表上剔除了一条新闻,实际却删除了叁条,因为大家删除的那本书在Book_authors表中有两条有关新闻,这种删除格局正是django暗许的级联删除。

假使是多对多的涉嫌: remove()和clear()方法: 

#正向
book = models.Book.objects.filter(id=1)

#删除第三张表中和女孩1关联的所有关联信息
book.author.clear()        #清空与book中id=1 关联的所有数据
book.author.remove(2)  #可以为id
book.author.remove(*[1,2,3,4])     #可以为列表,前面加*

#反向
author = models.Author.objects.filter(id=1)
author.book_set.clear() #清空与boy中id=1 关联的所有数据

**-----------------------------------------改(update和save) ----------------------------------------**

实例:

    www.weide1946.com 198

注意:

<一> 第3种方法修改不能够用get的彻头彻尾的经过是:update是QuerySet对象的主意,get再次回到的是四个model对象,它从未update方法,而filter再次来到的是多少个QuerySet对象(filter里面包车型地铁尺码或者有五个规格相符,比如name='alvin',只怕有几个name='alvin'的行数据)。

<2>在“插入和更新数据”小节中,我们有提到模型的save()方法,这个方法会更新一行里的所有列。 而某些情况下,我们只需要更新行里的某几列。

www.weide1946.com 199www.weide1946.com 200

#---------------- update方法直接设定对应属性----------------
    models.Book.objects.filter(id=3).update(title="PHP")
    ##sql:
    ##UPDATE "app01_book" SET "title" = 'PHP' WHERE "app01_book"."id" = 3; args=('PHP', 3)


#--------------- save方法会将所有属性重新设定一遍,效率低-----------
    obj=models.Book.objects.filter(id=3)[0]
    obj.title="Python"
    obj.save()
# SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price", 
# "app01_book"."color", "app01_book"."page_num", 
# "app01_book"."publisher_id" FROM "app01_book" WHERE "app01_book"."id" = 3 LIMIT 1; 
# 
# UPDATE "app01_book" SET "title" = 'Python', "price" = 3333, "color" = 'red', "page_num" = 556,
# "publisher_id" = 1 WHERE "app01_book"."id" = 3; 

View Code

      在这一个事例里大家得以见到Django的save()方法创新了非可是title列的值,还有革新了富有的列。 若title以外的列有比相当的大概率会被其余的经过所改造的事态下,只改动title列明显是进一步精明的。改动某一钦定的列,我们能够调用结果集(QuerySet)对象的update()方法,与之等同的SQL语句变得更飞速,并且不会挑起竞态条件。

除此以外,update()方法对于其他结果集(QuerySet)均有效,那代表你能够同时立异多条记录update()方法会重返贰个整型数值,表示受影响的记录条数。

留神,这里因为update重回的是多个整形,所以无法用query属性;对于每一回成立1个对象,想体现相应的raw sql,必要在settings加上日志记录部分:

www.weide1946.com 201www.weide1946.com 202

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

LOGGING

留意:即使是多对多的改:

 

    obj=Book.objects.filter(id=1)[0]
    author=Author.objects.filter(id__gt=2)

    obj.author.clear()
    obj.author.add(*author)

 

 

**---------------------------------------查(filter,value等)


---------->查询API:

www.weide1946.com 203www.weide1946.com 204

# 查询相关API:

#  <1>filter(**kwargs):      它包含了与所给筛选条件相匹配的对象

#  <2>all():                 查询所有结果

#  <3>get(**kwargs):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。

#-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()--------

#  <4>values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列

#  <5>exclude(**kwargs):     它包含了与所给筛选条件不匹配的对象

#  <6>order_by(*field):      对查询结果排序

#  <7>reverse():             对查询结果反向排序

#  <8>distinct():            从返回结果中剔除重复纪录

#  <9>values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

#  <10>count():              返回数据库中匹配查询(QuerySet)的对象数量。

# <11>first():               返回第一条记录

# <12>last():                返回最后一条记录

#  <13>exists():             如果QuerySet包含数据,就返回True,否则返回False。

View Code

补充:

www.weide1946.com 205www.weide1946.com 206

#扩展查询,有时候DJANGO的查询API不能方便的设置查询条件,提供了另外的扩展查询方法extra:
#extra(select=None, where=None, params=None, tables=None,order_by=None, select_params=None

(1)  Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
(2)  Blog.objects.extra(
        select=SortedDict([('a', '%s'), ('b', '%s')]),
        select_params=('one', 'two'))

(3)  q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
     q = q.extra(order_by = ['-is_recent'])

(4)  Entry.objects.extra(where=['headline=%s'], params=['Lennon'])  

extra

---------->惰性机制:

所谓惰性机制:Publisher.objects.all()可能.filter()等都只是重返了3个QuerySet(查询结果集对象),它并不会立时执行sql,而是当调用QuerySet的时候才施行。

QuerySet特点:

       <一>  可迭代的

       <2>  可切片

www.weide1946.com 207www.weide1946.com 208

    #objs=models.Book.objects.all()#[obj1,obj2,ob3...]

    #QuerySet:   可迭代

    # for obj in objs:#每一obj就是一个行对象
    #     print("obj:",obj)
    # QuerySet:  可切片

    # print(objs[1])
    # print(objs[1:4])
    # print(objs[::-1])

View Code

QuerySet的短平快利用:

www.weide1946.com 209www.weide1946.com 210

<1>Django的queryset是惰性的

     Django的queryset对应于数据库的若干记录(row),通过可选的查询来过滤。例如,下面的代码会得
     到数据库中名字为‘Dave’的所有的人:person_set = Person.objects.filter(first_name="Dave")
     上面的代码并没有运行任何的数据库查询。你可以使用person_set,给它加上一些过滤条件,或者将它传给某个函数,
     这些操作都不会发送给数据库。这是对的,因为数据库查询是显著影响web应用性能的因素之一。

<2>要真正从数据库获得数据,你可以遍历queryset或者使用if queryset,总之你用到数据时就会执行sql.
   为了验证这些,需要在settings里加入 LOGGING(验证方式)
        obj=models.Book.objects.filter(id=3)
        # for i in obj:
        #     print(i)

        # if obj:
        #     print("ok")

<3>queryset是具有cache的
     当你遍历queryset时,所有匹配的记录会从数据库获取,然后转换成Django的model。这被称为执行
    (evaluation).这些model会保存在queryset内置的cache中,这样如果你再次遍历这个queryset,
     你不需要重复运行通用的查询。
        obj=models.Book.objects.filter(id=3)

        # for i in obj:
        #     print(i)
                          ## models.Book.objects.filter(id=3).update(title="GO")
                          ## obj_new=models.Book.objects.filter(id=3)
        # for i in obj:
        #     print(i)   #LOGGING只会打印一次

<4>
     简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些
     数据!为了避免这个,可以用exists()方法来检查是否有数据:

            obj = Book.objects.filter(id=4)
            #  exists()的检查可以避免数据放入queryset的cache。
            if obj.exists():
                print("hello world!")

<5>当queryset非常巨大时,cache会成为问题

     处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统
     进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法
     来获取数据,处理完数据就将其丢弃。
        objs = Book.objects.all().iterator()
        # iterator()可以一次只从数据库获取少量数据,这样可以节省内存
        for obj in objs:
            print(obj.name)
        #BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了
        for obj in objs:
            print(obj.name)

     #当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使
     #用iterator()的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询

总结:
    queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。
使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能
会造成额外的数据库查询。

View Code

---------->对象查询,单表条件查询,多表口径关联合检查询

www.weide1946.com 211www.weide1946.com 212

#--------------------对象形式的查找--------------------------
    # 正向查找
    ret1=models.Book.objects.first()
    print(ret1.title)
    print(ret1.price)
    print(ret1.publisher)
    print(ret1.publisher.name)  #因为一对多的关系所以ret1.publisher是一个对象,而不是一个queryset集合

    # 反向查找
    ret2=models.Publish.objects.last()
    print(ret2.name)
    print(ret2.city)
    #如何拿到与它绑定的Book对象呢?
    print(ret2.book_set.all()) #ret2.book_set是一个queryset集合

#---------------了不起的双下划线(__)之单表条件查询----------------

#    models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
#
#    models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
#    models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
#
#    models.Tb1.objects.filter(name__contains="ven")
#    models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
#
#    models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and
#
#    startswith,istartswith, endswith, iendswith,

#----------------了不起的双下划线(__)之多表条件关联查询---------------

# 正向查找(条件)

#     ret3=models.Book.objects.filter(title='Python').values('id')
#     print(ret3)#[{'id': 1}]

      #正向查找(条件)之一对多

      ret4=models.Book.objects.filter(title='Python').values('publisher__city')
      print(ret4)  #[{'publisher__city': '北京'}]

      #正向查找(条件)之多对多
      ret5=models.Book.objects.filter(title='Python').values('author__name')
      print(ret5)
      ret6=models.Book.objects.filter(author__name="alex").values('title')
      print(ret6)

      #注意
      #正向查找的publisher__city或者author__name中的publisher,author是book表中绑定的字段
      #一对多和多对多在这里用法没区别

# 反向查找(条件)

    #反向查找之一对多:
    ret8=models.Publisher.objects.filter(book__title='Python').values('name')
    print(ret8)#[{'name': '人大出版社'}]  注意,book__title中的book就是Publisher的关联表名

    ret9=models.Publisher.objects.filter(book__title='Python').values('book__authors')
    print(ret9)#[{'book__authors': 1}, {'book__authors': 2}]

    #反向查找之多对多:
    ret10=models.Author.objects.filter(book__title='Python').values('name')
    print(ret10)#[{'name': 'alex'}, {'name': 'alvin'}]

    #注意
    #正向查找的book__title中的book是表名Book
    #一对多和多对多在这里用法没区别

View Code

留神:条件查询即与目标查询相应,是指在filter,values等方法中的通过__来明显询问条件。

---------->聚合查询和分组查询

<1> aggregate(*args,**kwargs):

   通过对QuerySet实行总计,再次回到二个聚合值的字典。aggregate()中每三个参数都钦命八个含有在字典中的再次回到值。即在查询集上生成聚合。

www.weide1946.com 213www.weide1946.com 214

from django.db.models import Avg,Min,Sum,Max

从整个查询集生成统计值。比如,你想要计算所有在售书的平均价钱。Django的查询语法提供了一种方式描述所有
图书的集合。

>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35}

aggregate()子句的参数描述了我们想要计算的聚合值,在这个例子中,是Book模型中price字段的平均值

aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的
标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定
一个名称,可以向聚合子句提供它:
>>> Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}


如果你也想知道所有图书价格的最大值和最小值,可以这样查询:
>>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}

View Code

<2> annotate(*args,**kwargs):

   能够通过计算查询结果中每二个对象所涉及的靶子群集,从而得出总结值(也能够是平均值或总和),即为查询集的每一种生成聚合。

       查询alex出的书总价格                   

       www.weide1946.com 215

        查询种种笔者出的书的总价格,这里就关系到分组了,分组条件是authors__name

       www.weide1946.com 216    

         查询种种出版社最有益的书价是多少

       www.weide1946.com 217

---------->F查询和Q查询

单单靠单壹的首要字参数查询已经很难满意查询供给。此时Django为大家提供了F和Q查询:

www.weide1946.com 218www.weide1946.com 219

# F 使用查询条件的值,专门取对象中某列值的操作

    # from django.db.models import F
    # models.Tb1.objects.update(num=F('num') 1)


# Q 构建搜索条件
    from django.db.models import Q

    #1 Q对象(django.db.models.Q)可以对关键字参数进行封装,从而更好地应用多个查询
    q1=models.Book.objects.filter(Q(title__startswith='P')).all()
    print(q1)#[<Book: Python>, <Book: Perl>]

    # 2、可以组合使用&,|操作符,当一个操作符是用于两个Q的对象,它产生一个新的Q对象。
    Q(title__startswith='P') | Q(title__startswith='J')

    # 3、Q对象可以用~操作符放在前面表示否定,也可允许否定与不否定形式的组合
    Q(title__startswith='P') | ~Q(pub_date__year=2005)

    # 4、应用范围:

    # Each lookup function that takes keyword-arguments (e.g. filter(),
    #  exclude(), get()) can also be passed one or more Q objects as
    # positional (not-named) arguments. If you provide multiple Q object
    # arguments to a lookup function, the arguments will be “AND”ed
    # together. For example:

    Book.objects.get(
        Q(title__startswith='P'),
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
    )

    #sql:
    # SELECT * from polls WHERE question LIKE 'P%'
    #     AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

    # import datetime
    # e=datetime.date(2005,5,6)  #2005-05-06

    # 5、Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面。
    # 正确:
    Book.objects.get(
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
        title__startswith='P')
    # 错误:
    Book.objects.get(
        question__startswith='P',
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))

View Code

ORM之查(filter,value) 

raw sql

django中models的操作,也是调用了O智跑M框架来达成的,pymysql 也许mysqldb,所以大家也足以利用原生的SQL语句来操作数据库!

查询API:

www.weide1946.com 220

# 查询相关API:

#  <1>filter(**kwargs):      它包含了与所给筛选条件相匹配的对象

#  <2>all():                 查询所有结果

#  <3>get(**kwargs):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。

#-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()--------

#  <4>values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列

#  <5>exclude(**kwargs):     它包含了与所给筛选条件不匹配的对象

#  <6>order_by(*field):      对查询结果排序

#  <7>reverse():             对查询结果反向排序

#  <8>distinct():            从返回结果中剔除重复纪录

#  <9>values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

#  <10>count():              返回数据库中匹配查询(QuerySet)的对象数量。

#  <11>first():               返回第一条记录

#  <12>last():                返回最后一条记录

#  <13>exists():             如果QuerySet包含数据,就返回True,否则返回False

www.weide1946.com 221

www.weide1946.com 222 View Code

九 admin的配置

admin是django强概略义之一,它能共从数据库中读取数据,呈现在页面中,实行管理。私下认可情状下,它的功用已经不行强劲,假使您无需复杂的功用,它已经够用,然而有时,一些差异日常的效用还索要定制,比如寻找效果,上边那1五种作品就渐渐深入介绍如何定制符合本人的admin应用。

假定您以为英文分界面不佳用,能够在setting.py 文件中期维修改以下选项

LANGUAGE_CODE = 'en-us'  #LANGUAGE_CODE = 'zh-hans'

一  认识ModelAdmin

   管理分界面包车型大巴定制类,如需扩展特定的model分界面需从该类承继。

贰 注册medel类到admin的二种方式:

     <1>   使用register的方法

admin.site.register(Book,MyAdmin)

     <2>   使用register的装饰器

@admin.register(Book)

三 掌握一些常用的装置才具

  •     list_display:     钦点要体现的字段
  •     search_田野先生s:  钦点搜索的字段
  •     list_filter:        内定列表过滤器
  •     ordering:       内定排序字段

    from django.contrib import admin from app01.models import * # Register your models here.

    # @admin.register(Book)#----->单给某些表加四个定制 class MyAdmin(admin.ModelAdmin):

    list_display = ("title","price","publisher")
    search_fields = ("title","publisher")
    list_filter = ("publisher",)
    ordering = ("price",)
    fieldsets =[
        (None,               {'fields': ['title']}),
        ('price information', {'fields': ['price',"publisher"], 'classes': ['collapse']}),
    ]
    

    admin.site.register(Book,MyAdmin) admin.site.register(Publish) admin.site.register(Author)

 

参考文献:

 

 

 

 

QuerySet与惰性机制

所谓惰性机制:Publisher.objects.all()恐怕.filter()等都只是回去了叁个QuerySet(查询结果集对象),它并不会即刻推行sql,而是当调用QuerySet的时候才推行。

QuerySet特点:

       <一>  可迭代的

       <2>  可切片

www.weide1946.com 223

    #objs=models.Book.objects.all()#[obj1,obj2,ob3...]

    #QuerySet:   可迭代

    # for obj in objs:#每一obj就是一个行对象
    #     print("obj:",obj)
    # QuerySet:  可切片

    # print(objs[1])
    # print(objs[1:4])
    # print(objs[::-1])

www.weide1946.com 224

QuerySet的飞跃利用:

www.weide1946.com 225www.weide1946.com 226

<1>Django的queryset是惰性的

     Django的queryset对应于数据库的若干记录(row),通过可选的查询来过滤。例如,下面的代码会得
     到数据库中名字为‘Dave’的所有的人:person_set = Person.objects.filter(first_name="Dave")
     上面的代码并没有运行任何的数据库查询。你可以使用person_set,给它加上一些过滤条件,或者将它传给某个函数,
     这些操作都不会发送给数据库。这是对的,因为数据库查询是显著影响web应用性能的因素之一。

<2>要真正从数据库获得数据,你可以遍历queryset或者使用if queryset,总之你用到数据时就会执行sql.
   为了验证这些,需要在settings里加入 LOGGING(验证方式)
        obj=models.Book.objects.filter(id=3)
        # for i in obj:
        #     print(i)

        # if obj:
        #     print("ok")

<3>queryset是具有cache的
     当你遍历queryset时,所有匹配的记录会从数据库获取,然后转换成Django的model。这被称为执行
    (evaluation).这些model会保存在queryset内置的cache中,这样如果你再次遍历这个queryset,
     你不需要重复运行通用的查询。
        obj=models.Book.objects.filter(id=3)

        # for i in obj:
        #     print(i)
                          ## models.Book.objects.filter(id=3).update(title="GO")
                          ## obj_new=models.Book.objects.filter(id=3)
        # for i in obj:
        #     print(i)   #LOGGING只会打印一次

<4>
     简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些
     数据!为了避免这个,可以用exists()方法来检查是否有数据:

            obj = Book.objects.filter(id=4)
            #  exists()的检查可以避免数据放入queryset的cache。
            if obj.exists():
                print("hello world!")

<5>当queryset非常巨大时,cache会成为问题

     处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统
     进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法
     来获取数据,处理完数据就将其丢弃。
        objs = Book.objects.all().iterator()
        # iterator()可以一次只从数据库获取少量数据,这样可以节省内存
        for obj in objs:
            print(obj.name)
        #BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了
        for obj in objs:
            print(obj.name)

     #当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使
     #用iterator()的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询

总结:
    queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。
使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能
会造成额外的数据库查询。

View Code

目的查询,单表条件查询,多表口径关联查询

www.weide1946.com 227

#--------------------对象形式的查找--------------------------
    # 正向查找
    ret1=models.Book.objects.first()
    print(ret1.title)
    print(ret1.price)
    print(ret1.publisher)
    print(ret1.publisher.name)  #因为一对多的关系所以ret1.publisher是一个对象,而不是一个queryset集合

    # 反向查找
    ret2=models.Publish.objects.last()
    print(ret2.name)
    print(ret2.city)
    #如何拿到与它绑定的Book对象呢?
    print(ret2.book_set.all()) #ret2.book_set是一个queryset集合

#---------------了不起的双下划线(__)之单表条件查询----------------

#    models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
#
#    models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
#    models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
#
#    models.Tb1.objects.filter(name__contains="ven")
#    models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
#
#    models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and
#
#    startswith,istartswith, endswith, iendswith,

#----------------了不起的双下划线(__)之多表条件关联查询---------------

# 正向查找(条件)

#     ret3=models.Book.objects.filter(title='Python').values('id')
#     print(ret3)#[{'id': 1}]

      #正向查找(条件)之一对多

      ret4=models.Book.objects.filter(title='Python').values('publisher__city')
      print(ret4)  #[{'publisher__city': '北京'}]

      #正向查找(条件)之多对多
      ret5=models.Book.objects.filter(title='Python').values('author__name')
      print(ret5)
      ret6=models.Book.objects.filter(author__name="alex").values('title')
      print(ret6)

      #注意
      #正向查找的publisher__city或者author__name中的publisher,author是book表中绑定的字段
      #一对多和多对多在这里用法没区别

# 反向查找(条件)

    #反向查找之一对多:
    ret8=models.Publisher.objects.filter(book__title='Python').values('name')
    print(ret8)#[{'name': '人大出版社'}]  注意,book__title中的book就是Publisher的关联表名

    ret9=models.Publisher.objects.filter(book__title='Python').values('book__authors')
    print(ret9)#[{'book__authors': 1}, {'book__authors': 2}]

    #反向查找之多对多:
    ret10=models.Author.objects.filter(book__title='Python').values('name')
    print(ret10)#[{'name': 'alex'}, {'name': 'alvin'}]

    #注意
    #正向查找的book__title中的book是表名Book
    #一对多和多对多在这里用法没区别

www.weide1946.com 228

专注:条件查询即与目的查询相应,是指在filter,values等措施中的通过__来家弦户诵询问条件。

汇集查询和分组查询

<1> aggregate(*args,**kwargs):

   通过对QuerySet举行测算,再次来到二个聚合值的字典。aggregate()中每一个参数都钦定二个带有在字典中的重回值。即在查询集上生成聚合。

www.weide1946.com 229www.weide1946.com 230

from django.db.models import Avg,Min,Sum,Max

从整个查询集生成统计值。比如,你想要计算所有在售书的平均价钱。Django的查询语法提供了一种方式描述所有
图书的集合。

>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35}

aggregate()子句的参数描述了我们想要计算的聚合值,在这个例子中,是Book模型中price字段的平均值

aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的
标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定
一个名称,可以向聚合子句提供它:
>>> Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}


如果你也想知道所有图书价格的最大值和最小值,可以这样查询:
>>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}

View Code

<2> annotate(*args,**kwargs):

   能够经过估测计算查询结果中每多个对象所波及的对象集合,从而得出总括值(也得以是平均值或总和),即为查询集的每1项生成聚合。

       查询alex出的书总价格      

       www.weide1946.com 231

       询问各类小编出的书的总价格,这里就关乎到分组了,分组条件是authors__name

       www.weide1946.com 232   

       查询各种出版社最利于的书价是不怎么

       www.weide1946.com 233

F查询和Q查询

只有靠单纯的主要性字参数查询已经很难满意查询供给。此时Django为我们提供了F和Q查询:

www.weide1946.com 234www.weide1946.com 235

# F 使用查询条件的值,专门取对象中某列值的操作

    # from django.db.models import F
    # models.Tb1.objects.update(num=F('num') 1)


# Q 构建搜索条件
    from django.db.models import Q

    #1 Q对象(django.db.models.Q)可以对关键字参数进行封装,从而更好地应用多个查询
    q1=models.Book.objects.filter(Q(title__startswith='P')).all()
    print(q1)#[<Book: Python>, <Book: Perl>]

    # 2、可以组合使用&,|操作符,当一个操作符是用于两个Q的对象,它产生一个新的Q对象。
    Q(title__startswith='P') | Q(title__startswith='J')

    # 3、Q对象可以用~操作符放在前面表示否定,也可允许否定与不否定形式的组合
    Q(title__startswith='P') | ~Q(pub_date__year=2005)

    # 4、应用范围:

    # Each lookup function that takes keyword-arguments (e.g. filter(),
    #  exclude(), get()) can also be passed one or more Q objects as
    # positional (not-named) arguments. If you provide multiple Q object
    # arguments to a lookup function, the arguments will be “AND”ed
    # together. For example:

    Book.objects.get(
        Q(title__startswith='P'),
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
    )

    #sql:
    # SELECT * from polls WHERE question LIKE 'P%'
    #     AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

    # import datetime
    # e=datetime.date(2005,5,6)  #2005-05-06

    # 5、Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面。
    # 正确:
    Book.objects.get(
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
        title__startswith='P')
    # 错误:
    Book.objects.get(
        question__startswith='P',
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))

View Code

admin的配置

admin是django强大功能之一,它能共从数据库中读取数据,呈今后页面中,实行处理。暗中同意情况下,它的意义已经越来越庞大,借让你不供给复杂的机能,它曾经够用,然则有时,一些特种的作用还亟需定制,比如搜索效果,下边那一多元文章就逐渐长远介绍如何定制符合本人的admin应用。

壹经您感到英文分界面不佳用,能够在setting.py 文件中期维修改以下选项

LANGUAGE_CODE = 'en-us'  #LANGUAGE_CODE = 'zh-hans'

一  认识ModelAdmin

   管理界面包车型大巴定制类,如需扩张特定的model分界面需从该类传承。

贰 注册medel类到admin的二种艺术:

<1>   使用register的方法

admin.site.register(Book,MyAdmin)

<二>   使用register的装饰器

@admin.register(Book)

叁 驾驭一些常用的安装本事

  •     list_display:     钦点要出示的字段
  •     search_田野s:  内定寻觅的字段
  •     list_filter:        钦定列表过滤器
  •     ordering:       钦点排序字段

 

www.weide1946.com 236

from django.contrib import admin
from app01.models import *
# Register your models here.

# @admin.register(Book)#----->单给某个表加一个定制
class MyAdmin(admin.ModelAdmin):
    list_display = ("title","price","publisher")
    search_fields = ("title","publisher")
    list_filter = ("publisher",)
    ordering = ("price",)
    fieldsets =[
        (None,               {'fields': ['title']}),
        ('price information', {'fields': ['price',"publisher"], 'classes': ['collapse']}),
    ]

admin.site.register(Book,MyAdmin)
admin.site.register(Publish)
admin.site.register(Author)

www.weide1946.com 237

 

版权声明:本文由韦德娱乐1946_韦德娱乐1946网页版|韦德国际1946官网发布于网络编程,转载请注明出处:一周后的重温