zoukankan      html  css  js  c++  java
  • Python Web框架——Django

    返回顶部

    使用框架简单快速开发特定的系统。

    pip freeze > requirements.txt

    pip install -r requirements.txt

    一 MVC和MTV模式

    二 简介

    Django时有Python开发的一个免费的开源网站框架,可以用于快速搭建高性能、优雅的网站。

    Django框架的特点:

    • 强大的数据库功能
    • 自带强大的后台功能
    • 通过正则匹配随意定义的网址
    • 强大易扩展的模板系统
    • 缓存系统
    • 国际化

    三 Django安装方式

    1.利用pip安装Django。

    oliver@oliver-G460:~$ sudo pip3 install Django
    

    2.利用源码包安装Django。

    oliver@oliver-G460:~$ tar -zxvf django-1.10.xx.tar.gz
    

     解压后进入目录,执行:

    python3 setup.py install
    

    3.利用Linux自带源安装Django。

    sudo apt-get install python3-django
    

    检查Django是否安装成功:

    oliver@oliver-G460:~$ python3
    Python 3.5.2 (default, Sep 10 2016, 08:21:44) 
    [GCC 5.4.0 20160609] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import django
    >>> django.VERSION
    (1, 10, 2, 'final', 0)
    

     如果希望安装不同版本的Django环境,则需要通过virtualenv来管理多个开发环境。

    四 Django项目创建

    方式一:用命令创建项目和app

    1. 创建一个新的Django项目

    2. 创建app

    python3 manage.py startapp app-name 或 django-admin.py startapp app-name

    需要注意的是,通过命令行创建的项目,在settings.py中,如app名称和模板路径及templates目录等信息要自己添加。

    方式二:用Pycharm创建

    在File→New Project中选择Django,输入项目名称mysite和应用名称myApp,完成创建。

    创建完成后, 用Pycharm打开项目,查看项目和app目录文件

    • manage.py:用于管理Django站点。
    • settings.py:项目所有的配置信息,包含项目默认设置,数据库信息,调试标识以及其它工作变量等。
    • urls.py:负责把URL映射到视图函数,即路由系统。
    • wsgi.py:内置runserver命令的WSGI应用配置。

     五 Django urls(路由系统)

     即urls.py文件。其本质是建立url与其所调用的视图函数的映射关系,以此来规定访问什么网址去对应什么内容,执行哪个视图函数。

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

     说明(括号中四部分的意义):

    • 正则表达式字符串来匹配浏览器发送到服务端的URL网址
    • 可调用的视图函数对象。先引入(import)再使用
    • 要传给视图函数的默认参数(字典形式)
    • name,即别名。HTML中form表单参数action属性值使用此别名后,即便url发生变化,也无需在HTML中批量进行修改。

    1 URL配置举例:

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

    用()括起来表示保存为一个子组,每个子组作为一个参数(无名参数),被views.py中的对应函数接收。参数个数与视图函数中的形参个数要保持一致。

    (注意:当匹配到第一个url后立即返回,不再向下查找匹配。)

    2 带命名的组Named group(?P<>)用法

    ?P<group_name> 表示带命名的参数,例如:将year='2016'作为一个整体传个视图函数。此处的组名称必须与视图函数中的形参名称一致。由于有参数名称与之对应,所以视图函数有多个形参时,不需要考虑参数的先后顺序。

    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),  # year=2016
        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),
    ]

    3 默认参数(可选)

    如下所示,如果请求地址为/blog/2016,表示将year='2016',foo='bar'传给视图函数,视图函数中必须有相同名称的形参来接收值。

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

    4 name别名(可选)

     固定用法:

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

    如果url中的路径修改为/index2/,对应的模板,甚至还视图中的跳转,以及 models.py 中也可能有获取网址的地方。每个地方都要改,修改的代价很大,一不小心,有的地方没改过来,那个就不能用了。

    因此,在需要跳转或获取网址的地方,使用别名设置的名称,以后便可以随意修改url了。

    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

     5 URLconf

    一个网站包含成千上万个URL,如果所有的URL映射都放在一个文件下,很可能会出错,也不便与维护。

    因此,我们在每个app应用下分别创建一个urls目录,将不同的请求分发给不同app下的urls去匹配,如:对于/blog/index/请求直接交给‘blog.urls’去处理,清晰明确,更方便管理。

    六 Django views(视图函数)

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

    http请求:HttpRequest对象

    http响应:HttpResponse对象

    所在位置:django.http

    request就是指HttpRequest。

    1 HttpRequest对象的属性和方法

    属性 描述
    path 请求页面的全路径,不包括域名—例如, "/music/bands/the_beatles/"。
    method 请求中使用的HTTP方法的字符串表示。全大写表示。
    GET 包含所有HTTP GET参数的类字典对象
    POST 包含所有HTTP POST参数的类字典对象
    REQUEST 为了方便,该属性是POST和GET属性的集合体,但是有特殊性,先查找POST属性,然后再查找GET属性
    COOKIES 包含所有cookies的标准Python字典对象。Keys和values都是字符串。
    FILES 包含所有上传文件的类字典对象。FILES中的每个Key都是<input type="file" name="" />标签中name属性的值. FILES中的每个value 同时也是一个标准Python字典对象,包含下面三个Keys:(Filename: 上传文件名,用Python字符串表示;content-type: 上传文件的Content type;content: 上传文件的原始内容)注意:只有在请求方法是POST,并且请求页面中<form>enctype="multipart/form-data"属性时FILES才拥有数据。否则,FILES 是一个空字典。
    META 包含所有可用HTTP头部信息的字典,例如:(CONTENT_LENGTH,CONTENT_TYPE,QUERY_STRING: 未解析的原始查询字符,串,REMOTE_ADDR: 客户端IP地址REMOTE_HOST: 客户端主机名,SERVER_NAME: 服务器主机名,SERVER_PORT: 服务器端口);META 中这些头加上前缀HTTP_最为Key, 例如:(HTTP_ACCEPT_ENCODING,HTTP_ACCEPT_LANGUAGE,HTTP_HOST: 客户发送的HTTP主机头信息,HTTP_REFERER: referring页,HTTP_USER_AGENT: 客户端的user-agent字符串,HTTP_X_BENDER: X-Bender头信息)
    user 是一个django.contrib.auth.models.User 对象,代表当前登录的用户。如果访问用户当前没有登录,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。见例子1
    session 唯一可读写的属性,代表当前会话的字典对象。只有激活Django中的session支持时该属性才可用。
    raw_post_data 原始HTTP POST数据,未解析过。 高级处理时会有用处。
    method 描述
    __getitem__(key) 返回GET/POST的键值,先取POST,后取GET。如果键不存在抛出 KeyError。这是我们可以使用字典语法访问HttpRequest对象。例如:request["foo"]等同于先request.POST["foo"] 然后 request.GET["foo"]的操作。
    has_key() 检查request.GET or request.POST中是否包含参数指定的Key。
    get_full_path() 返回包含查询字符串的请求路径。例如, "/music/bands/the_beatles/?print=true"
    is_secure() 如果请求是安全的,返回True,就是说,发出的是HTTPS请求。
    get_full_path(),   比如:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()得到的结果就是/index33/?name=123
    req.path得到的结果是:/index33

    2 HttpResponse对象的属性和方法

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

      HttpResponse类在django.http.HttpResponse

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

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

    七 Django templates(模板)

     模板由HTML+逻辑控制代码组成。

    1 变量

    使用双大括号来引用变量

    语法格式:       {{var_name}}
    

    2 Template和Context对象

    渲染操作流程:

    一旦创建Template对象之后,可以用context传递数据给它,它是一系列变量和它们值的集合,模板使用它来赋值模板变量标签和执行块标签

    context在django里表现为Context类,在django.template模块中

    Context类构造是一个可选参数:一个字典映射变量和它们的值

    创建一系列Context对象之后,调用Template对象的render()方法并传递Context对象来填充模板

    同一个模板渲染多个context:

    1 >>>from django,template import Template,Context
    2 >>>t=Template("My name is {{name}},I love{{language}}")
    3 >>>c=Context({'name':'BeginMan','language':'Python/Js/C#'})
    4 >>>t.render(c)
    5 --------------------------------output----------------------------------------------
    6 My name is BeginMan ,I love Python/Js/C#


    推荐写法:

    def current_time(req):
    
        now=datetime.datetime.now()
    
        return render(req, 'current_datetime.html', {'current_date':now})    # 字典部分指定就是Context对象,render()方法将Context对象的键值传递给模板,并填充模板。
    

     3 深度变量查找

    context不仅能传递简单的参数(字符串),也可以传递列表和字典对象。

     1 #最好是用几个例子来说明一下。
     2 # 首先,句点可用于访问列表索引,例如:
     3 
     4 >>> from django.template import Template, Context
     5 >>> t = Template('Item 2 is {{ items.2 }}.')
     6 >>> c = Context({'items': ['apples', 'bananas', 'carrots']})
     7 >>> t.render(c)
     8 'Item 2 is carrots.'
     9 
    10 #假设你要向模板传递一个 Python 字典。 要通过字典键访问该字典的值,可使用一个句点:
    11 >>> from django.template import Template, Context
    12 >>> person = {'name': 'Sally', 'age': '43'}
    13 >>> t = Template('{{ person.name }} is {{ person.age }} years old.')
    14 >>> c = Context({'person': person})
    15 >>> t.render(c)
    16 'Sally is 43 years old.'
    17 
    18 #同样,也可以通过句点来访问对象的属性。 比方说, Python 的 datetime.date 对象有
    19 #year 、 month 和 day 几个属性,你同样可以在模板中使用句点来访问这些属性:
    20 
    21 >>> from django.template import Template, Context
    22 >>> import datetime
    23 >>> d = datetime.date(1993, 5, 2)
    24 >>> d.year
    25 >>> d.month
    26 >>> d.day
    27 >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
    28 >>> c = Context({'date': d})
    29 >>> t.render(c)
    30 'The month is 5 and the year is 1993.'
    31 
    32 # 这个例子使用了一个自定义的类,演示了通过实例变量加一点(dots)来访问它的属性,这个方法适
    33 # 用于任意的对象。
    34 >>> from django.template import Template, Context
    35 >>> class Person(object):
    36 ...     def __init__(self, first_name, last_name):
    37 ...         self.first_name, self.last_name = first_name, last_name
    38 >>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')
    39 >>> c = Context({'person': Person('John', 'Smith')})
    40 >>> t.render(c)
    41 'Hello, John Smith.'
    42 
    43 # 点语法也可以用来引用对象的方法。 例如,每个 Python 字符串都有 upper() 和 isdigit()
    44 # 方法,你在模板中可以使用同样的句点语法来调用它们:
    45 >>> from django.template import Template, Context
    46 >>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')
    47 >>> t.render(Context({'var': 'hello'}))
    48 'hello -- HELLO -- False'
    49 >>> t.render(Context({'var': '123'}))
    50 '123 -- 123 -- True'
    51 
    52 # 注意这里调用方法时并* 没有* 使用圆括号 而且也无法给该方法传递参数;你只能调用不需参数的
    53 # 方法。
    View Code

    4 变量过滤器filter

    语法格式:      {{obj|filter:param}}
    
     1 # 1  add          :   给变量加上相应的值
     2    #
     3    # 2  addslashes   :    给变量中的引号前加上斜线
     4    #
     5    # 3  capfirst     :    首字母大写
     6    #
     7    # 4  cut          :   从字符串中移除指定的字符
     8    #
     9    # 5  date         :   格式化日期字符串
    10    #
    11    # 6  default      :   如果值是False,就替换成设置的默认值,否则就是用本来的值
    12    #
    13    # 7  default_if_none:  如果值是None,就替换成设置的默认值,否则就使用本来的值
    14 
    15 
    16 #实例:
    17 
    18 #value1="aBcDe"
    19 {{ value1|upper }}
    20 
    21 #value2=5
    22 {{ value2|add:3 }}
    23 
    24 #value3='he  llo wo r ld'
    25 {{ value3|cut:' ' }}
    26 
    27 #import datetime
    28 #value4=datetime.datetime.now()
    29 {{ value4|date:'Y-m-d' }}
    30 
    31 #value5=[]
    32 {{ value5|default:'空的' }}
    33 
    34 #value6='<a href="#">跳转</a>'
    35 
    36 {{ value6 }}
    37 
    38 {% autoescape off %}
    39   {{ value6 }}
    40 {% endautoescape %}
    41 
    42 {{ value6|safe }}
    43 
    44 {{ value6|striptags }}
    45 
    46 #value7='1234'
    47 {{ value7|filesizeformat }}
    48 {{ value7|first }}
    49 {{ value7|length }}
    50 {{ value7|slice:":-1" }}
    51 
    52 #value8='http://www.baidu.com/?a=1&b=3'
    53 {{ value8|urlencode }}
    54     value9='hello I am yuan'
    View Code

    5 常用标签(tag)

    语法格式:      {% tags %}
    

    (1)  {% if %}

    (2)  {% for %}

    (3)  {% csrf_token %}

    (4)  {% url %} :引用路由配置的地址

    (5)  {% with %} :用简短的变量名代替复杂的变量名

    (6) {% verbatim %} :禁止render

    (7) {% load %} :加载标签库

    6 自定义filter和simple_tag

    (1)在app下创建templatetags目录或模块,目录名称必须这样写。

    (2)创建.py文件,如my_tags。(其中,register名称不可改变)

    (3)在使用自定义filter和simple_tag的html文件之前,通过 {% load my_tags %}导入前面自己创建的my_tags标签库。(注意:settings中INSTALLED_APPS中必须添加当前的app名称,否则找不到自定义的tags)

    (4)调用自定义的filter和simple_tag。

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

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

    7 extend模板继承

    将shopping_car.html和ordered.html中大量重复的代码提取出来,写入base.html中,不同的部分分别写在各自模板中,通过extends继承base.html中的公共部分。

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6     <style>
     7         *{
     8             margin: 0;
     9         }
    10 
    11         .top{
    12             height: 45px;
    13             background-color: darkblue;
    14         }
    15 
    16         .menu{
    17             width: 20%;
    18             height: 700px;
    19             background-color: cornflowerblue;
    20             float: left;
    21             margin-top: 5px;
    22         }
    23 
    24         .menu a{
    25             display: block;
    26             text-align: center;
    27         }
    28 
    29         .content{
    30             width: 80%;
    31             height: 700px;
    32             float: left;
    33             margin-top: 5px;
    34             background-color: lightgray;
    35         }
    36     </style>
    37 </head>
    38 <body>
    39     <div class="top"></div>
    40     <div class="menu">
    41         <a href="/shopping_car/">Shopping Car</a>
    42         <a href="/ordered/">Ordered</a>
    43     </div>
    44     <div class="content">
    45         {% block content %}
    46         {% endblock %}
    47     </div>
    48 </body>
    49 </html>
    base.html

    shopping_car.html:

    1 {% extends 'base.html' %}
    2 
    3 
    4 {% block content %}
    5  <a>购物车</a>
    6 {% endblock %}

    ordered.html:

    1 {% extends 'base.html' %}
    2 
    3 
    4 {% block content %}
    5  <a>订单</a>
    6 {% endblock %}

    八 Django modules(模型)

    1      django默认支持sqlite,mysql, oracle,postgresql数据库。

         <1> sqlite

                django默认使用sqlite的数据库,默认自带sqlite的数据库驱动

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

         <2> mysql

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

    2    mysql驱动程序

              MySQLdb(mysql python)

              mysqlclient

              MySQL

              PyMySQL(纯python的mysql驱动程序)

    3  Django的项目中默认使用sqlite数据库,在settings中设置如下:

     如果想要使用mysql数据库,只需要做如下更改:

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

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

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

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

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

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

    ORM(对象关系映射)

    对象-关系映射(Object/Relation Mapping,简称ORM),是随着面向对象的软件开发方法发展而产生的。面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,关系数据库是企业级应用环境中永久存放数据的主流数据存储系统。对象和关系数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据。内存中的对象之间存在关联和继承关系,而在数据库中,关系数据无法直接表达多对多关联和继承关系。因此,对象-关系映射(ORM)系统一般以中间件的形式存在,主要实现程序对象到关系数据库数据的映射。  面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。  让我们从O/R开始。字母O起源于"对象"(Object),而R则来自于"关系"(Relational)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。  当你开发一个应用程序的时候(不使用O/R Mapping),你可能会写不少数据访问层的代码,用来从数据库保存,删除,读取对象信息,等等。你在DAL中写了很多的方法来读取对象数据,改变状态对象等等任务。而这些代码写起来总是重复的。  如果打开你最近的程序,看看DAL代码,你肯定会看到很多近似的通用的模式。我们以保存对象的方法为例,你传入一个对象,为SqlCommand对象添加SqlParameter,把所有属性和对象对应,设置SqlCommand的CommandText属性为存储过程,然后运行SqlCommand。对于每个对象都要重复的写这些代码。  除此之外,还有更好的办法吗?有,引入一个O/R Mapping。实质上,一个O/R Mapping会为你生成DAL。与其自己写DAL代码,不如用O/R Mapping。你用O/R Mapping保存,删除,读取对象,O/R Mapping负责生成SQL,你只需要关心对象就好。  对象关系映射成功运用在不同的面向对象持久层产品中,如:Torque,OJB,hibernate,TopLink,Castor JDO, TJDO 等。  

    一般的ORM包括以下四部分:  一个对持久类对象进行CRUD操作的API;  一个语言或API用来规定与类和类属性相关的查询;  一个规定mapping metadata的工具;  一种技术可以让ORM的实现同事务对象一起进行dirty checking, lazy association fetching以及其他的优化操作。

    1  django ORM——创建表(模型)

        django模型常用的字段类型

                    字段名

    参数

    意义

    AutoField

     

    一个能够根据可用ID自增的 IntegerField

    BooleanField

     

    一个真/假(true/false)字段

    CharField

     (max_length)

    一个字符串字段,适用于中小长度的字符串。对于长段的文字,请使用 TextField

    CommaSeparatedIntegerField

     (max_length)

    一个用逗号分隔开的整数字段

    DateField

    ([auto_now],  [auto_now_add])

    日期字段

    DateTimeField

     

    时间日期字段,接受跟 DateField 一样的额外选项

    EmailField

     

    一个能检查值是否是有效的电子邮件地址的 CharField

    FileField

    (upload_to)

    一个文件上传字段

    FilePathField

    (path,[match],[recursive])

    一个拥有若干可选项的字段,选项被限定为文件系统中某个目录下的文件名

    FloatField

    (max_digits,decimal_places)

    一个浮点数,对应Python中的 float 实例

    ImageField

    (upload_to,  [height_field] ,[width_field])

    像 FileField 一样,只不过要验证上传的对象是一个有效的图片。

    IntegerField

     

    一个整数。

    IPAddressField

     

    一个IP地址,以字符串格式表示(例如: "24.124.1.30" )。

    NullBooleanField

     

    就像一个  BooleanField ,但它支持 None /Null 。

    PhoneNumberField 

     

    它是一个  CharField ,并且会检查值是否是一个合法的美式电话格式

    PositiveIntegerField 

     

    和  IntegerField 类似,但必须是正值。

    PositiveSmallIntegerField 

     

    与  PositiveIntegerField 类似,但只允许小于一定值的值,最大值取决于数据库.

    SlugField

     

     嵌条 就是一段内容的简短标签,这段内容只能包含字母、数字、下

    划线或连字符。通常用于URL中

    SmallIntegerField

     

    和  IntegerField 类似,但是只允许在一个数据库相关的范围内的数值(通常是-32,768到

    +32,767)

    TextField

     

    一个不限长度的文字字段

    TimeField

     

    时分秒的时间显示。它接受的可指定参数与 DateField 和 DateTimeField 相同。

    URLField

     

    用来存储URL的字段。

    USStateField

     

    美国州名称缩写,两个字母。

    XMLField

    (schema_path)

    它就是一个  TextField ,只不过要检查值是匹配指定schema的合法XML。

     

     参数名

    意义

    null

    如果设置为 True 的话,Django将在数据库中存储空值为 NULL 。默认为 False 。

    blank

    如果是 True ,该字段允许留空,默认为 False 。

    choices

    一个包含双元素元组的可迭代的对象,用于给字段提供选项。

    db_column

    当前字段在数据库中对应的列的名字。

    db_index

    如果为 True ,Django会在创建表格(比如运行 manage.py syncdb )时对这一列创建数据库索引。

    default

    字段的默认值

    editable

    如果为 False ,这个字段在管理界面或表单里将不能编辑。默认为 True 。

    help_text

    在管理界面表单对象里显示在字段下面的额外帮助文本。

    primary_key

    如果为 True ,这个字段就会成为模型的主键。

    radio_admin

    默认地,对于  ForeignKey 或者拥有 choices  设置的字段,Django管理界面会使用列表选择框(<select>)。如果 radio_admin 设置为 True 的话,Django就会使用单选按钮界面。

    unique

    如果是 True ,这个字段的值在整个表中必须是唯一的。

    unique_for_date

    把它的值设成一个  DataField 或者  DateTimeField 的字段的名称,可以确保字段在这个日期内不会出现重复值。

    unique_for_month

      unique_for_date 类似,只是要求字段在指定字段的月份内唯一。

    unique_for_year

      unique_for_date 及 unique_for_month 类似,只是时间范围变成了一年。

    verbose_name

    ForeignKey  、  ManyToManyField 和 OneToOneField 之外的字段都接受一个详细名称作为第一个位置参数。

    实例:创建一个书籍、作者、出版社数据库结构

    一本书可能有多个作者,一个作者可以写多本书,一本书通常仅由一个出版社出版。因此作者与书为多对多关系,出版社与书为一对多关系。接下来,我们来创建表(模型)。

    多对多关系(many-to-many):彼此一对多,自动创建第三张表来表示对应关系。

    一对多关系(one-to-many):主外键关系,在many对应的表中给需要的字段添加外键。

    一对一(one-to-one):在一对多基础上,在多的哪个表ForeignKey的基础上加unique=true。

    1  每个数据模型都是django.db.models.Model的子类,它的父类Model包含了所有必要的和数据库交互的方法。并提供了一个简介漂亮的定义数据库字段的语法。      

    2  每个模型相当于单个数据库表(多对多关系例外,会多生成一张关系表),每个属性也是这个表中的字段。属性名就是字段名,它的类型(例如CharField)相当于数据库的字段类型(例如varchar)。

     1 from django.db import models
     2 
     3 # Create your models here.
     4 class Publisher(models.Model):
     5 
     6     name = models.CharField(max_length=64,verbose_name="出版社名称")
     7     city = models.CharField(max_length=24,verbose_name="所在城市")
     8 
     9 
    10     def __str__(self):
    11 
    12         return self.name
    13 
    14 
    15 class Author(models.Model):
    16 
    17     name = models.CharField(max_length=20,verbose_name="作者名称")
    18     sex = models.BooleanField(max_length=1,choices=((0,''),(1,'')))
    19     email = models.EmailField()
    20     birthday = models.DateField()
    21 
    22     def __str__(self):
    23 
    24         return self.name
    25 
    26 
    27 class Book(models.Model):
    28 
    29     title = models.CharField(max_length=64,verbose_name="书名")
    30     authors = models.ManyToManyField(Author)
    31     publish = models.ForeignKey(Publisher)
    32     price = models.DecimalField(max_digits=5,decimal_places=2,default=10)
    33 
    34     def __str__(self):
    35 
    36         return self.title
    创建模型

    确认当前app已经添加到settings设置中,然后执行数据库初始化操作: python3 manage.py makemigrationspython3 manage.py migrate

    2  django ORM——增(create、save)

    增加数据有两种方式: (数据表中的每一条数据代表一个对象)

    创建一对多关系:

    创建多对多关系:

    3  django ORM——删(delete)

     

    4  django ORM——改(update、save)

     只有QuerySet对象才有update方法,因此查找行对象时只能使用filter,不能使用get。返回的整数表示受影响的行数。

    save方法会将所有属性重新设定一遍,而update只对指定的属性值进行设定,故update方法更高效。

    5  django ORM——查

     1 # 查询相关API:
     2 
     3 #  <1>filter(**kwargs):      它包含了与所给筛选条件相匹配的对象
     4 
     5 #  <2>all():                 查询所有结果
     6 
     7 #  <3>get(**kwargs):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
     8 
     9 #-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()--------
    10 
    11 #  <4>values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列
    12                                      
    13 #  <5>exclude(**kwargs):     它包含了与所给筛选条件不匹配的对象
    14 
    15 #  <6>order_by(*field):      对查询结果排序
    16 
    17 #  <7>reverse():             对查询结果反向排序
    18 
    19 #  <8>distinct():            从返回结果中剔除重复纪录
    20 
    21 #  <9>values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
    22 
    23 #  <10>count():              返回数据库中匹配查询(QuerySet)的对象数量。
    24 
    25 # <11>first():               返回第一条记录
    26 
    27 # <12>last():                返回最后一条记录
    28 
    29 #  <13>exists():             如果QuerySet包含数据,就返回True,否则返回False。
    查询API:
    >>> Book.objects.all()
    <QuerySet [<Book: python>, <Book: php>, <Book: python红宝书>, <Book: C语言>, <Book: C++>, <Book: 杜拉拉大结局>, <Book: 百年孤独>]>
    >>> Book.objects.filter(price__lt=50)
    <QuerySet [<Book: python红宝书>, <Book: 杜拉拉大结局>, <Book: 百年孤独>]>
    >>> Book.objects.get(title='python')
    <Book: python>
    >>> Book.objects.filter(price__lt=50).values()
    <QuerySet [{'title': 'python红宝书', 'price': Decimal('8.00'), 'publish_id': 4, 'id': 3}, {'title': '杜拉拉大结局', 'price': Decimal('32.00'), 'publish_id': 3, 'id': 6}, {'title': '百年孤独', 'price': Decimal('39.50'), 'publish_id': 4, 'id': 7}]>
    >>> Book.objects.filter(price__lt=50).exclude(price__gt=60)
    <QuerySet [<Book: python红宝书>, <Book: 杜拉拉大结局>, <Book: 百年孤独>]>
    >>> Book.objects.filter(price__lt=50).exclude(id=6)
    <QuerySet [<Book: python红宝书>, <Book: 百年孤独>]>
    >>> Book.objects.all().order_by('price')
    <QuerySet [<Book: python红宝书>, <Book: 杜拉拉大结局>, <Book: 百年孤独>, <Book: C语言>, <Book: php>, <Book: python>, <Book: C++>]>
    >>> Book.objects.all().reverse()
    <QuerySet [<Book: python>, <Book: php>, <Book: python红宝书>, <Book: C语言>, <Book: C++>, <Book: 杜拉拉大结局>, <Book: 百年孤独>]>
    >>> Book.objects.all().distinct()
    <QuerySet [<Book: python>, <Book: php>, <Book: python红宝书>, <Book: C语言>, <Book: C++>, <Book: 杜拉拉大结局>, <Book: 百年孤独>]>
    >>> Book.objects.all().values_list()
    <QuerySet [(1, 'python', 1, Decimal('78.00')), (2, 'php', 2, Decimal('54.00')), (3, 'python红宝书', 4, Decimal('8.00')), (4, 'C语言', 2, Decimal('50.00')), (5, 'C++', 1, Decimal('78.00')), (6, '杜拉拉大结局', 3, Decimal('32.00')), (7, '百年孤独', 4, Decimal('39.50'))]>
    >>> Book.objects.all().count()
    7
    >>> Book.objects.all().first()
    <Book: python>
    >>> Book.objects.all().last()
    <Book: 百年孤独>
    >>> Book.objects.all().exists()
    True
    View Code

       扩展查询:

    #扩展查询,有时候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

       惰性机制:

    Book.objects.filter()或Book.objects.all()等只是返回一个QuerySet对象(查询结果集对象),并不会马上执行SQL,而是当调用QuerySet对象时才会执行SQL。

       QuerySet特点:

        <1>可迭代

       

        <2>可切片

      

      QuerySet的高效使用:

     1 #<1>Django的queryset是惰性的
     2 
     3 Django的queryset对应于数据库的若干记录(row),通过可选的查询来过滤。例如,下面的代码会得到数据库中
     4 名字为‘Dave’的所有的人:
     5 person_set = Person.objects.filter(first_name="Dave")
     6 
     7 上面的代码并没有运行任何的数据库查询。你可以使用person_set,给它加上一些过滤条件,或者将它传给某个函数,
     8 这些操作都不会发送给数据库。这是对的,因为数据库查询是显著影响web应用性能的因素之一。
     9 
    10 #<2>要真正从数据库获得数据,你可以遍历queryset或者使用if queryset,总之你用到数据时就会执行sql.
    11    为了验证这些,需要在settings里加入 LOGGING(验证方式)
    12 
    13         obj=models.Book.objects.filter(id=3)
    14 
    15         # for i in obj:
    16         #     print(i)
    17 
    18         # if obj:
    19         #     print("ok")
    20 
    21 #<3>queryset是具有cache的
    22 当你遍历queryset时,所有匹配的记录会从数据库获取,然后转换成Django的model。这被称为执行(evaluation).
    23 这些model会保存在queryset内置的cache中,这样如果你再次遍历这个queryset,你不需要重复运行通用的查询。
    24         obj=models.Book.objects.filter(id=3)
    25 
    26         # for i in obj:
    27         #     print(i)
    28 
    29         # for i in obj:
    30         #     print(i)   #LOGGING只会打印一次
    31 
    32 
    33 #<4>
    34      简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些数据!
    35 为了避免这个,可以用exists()方法来检查是否有数据:
    36 
    37 obj = Book.objects.filter(id=4)
    38 #  exists()的检查可以避免数据放入queryset的cache。
    39 if obj.exists():
    40     print("hello world!")
    41 
    42 #<5>当queryset非常巨大时,cache会成为问题
    43 
    44 处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统进程,让你的
    45 程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法来获取数据,处理完数据就
    46 将其丢弃。
    47 objs = Book.objects.all()
    48 # iterator()可以一次只从数据库获取少量数据,这样可以节省内存
    49 for obj in objs.iterator():
    50     print(obj.name)
    51 当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使用iterator()
    52 的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询
    53 
    54 总结:
    55     queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。
    56 使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能
    57 会造成额外的数据库查询。
    View Code

     对象查询、单表条件查询、多表条件关联查询:

     1 #--------------------对象形式的查找--------------------------
     2     # 正向查找
     3     ret1=models.Book.objects.first()
     4     print(ret1.title)
     5     print(ret1.price)
     6     print(ret1.publisher)
     7     print(ret1.publisher.name)  #因为一对多的关系所以ret1.publisher是一个对象,而不是一个queryset集合
     8 
     9     # 反向查找
    10     ret2=models.Publish.objects.last()
    11     print(ret2.name)
    12     print(ret2.city)
    13     #如何拿到与它绑定的Book对象呢?
    14     print(ret2.book_set.all()) #ret2.book_set是一个queryset集合
    15 
    16 #---------------了不起的双下划线(__)之单表条件查询----------------
    17 
    18 #    models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
    19 #
    20 #    models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
    21 #    models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
    22 #
    23 #    models.Tb1.objects.filter(name__contains="ven")
    24 #    models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
    25 #
    26 #    models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and
    27 #
    28 #    startswith,istartswith, endswith, iendswith,
    29 
    30 #----------------了不起的双下划线(__)之多表条件关联查询---------------
    31 
    32 # 正向查找(条件)
    33 
    34 #     ret3=models.Book.objects.filter(title='Python').values('id')
    35 #     print(ret3)#[{'id': 1}]
    36 
    37       #正向查找(条件)之一对多
    38 
    39       ret4=models.Book.objects.filter(title='Python').values('publisher__city')
    40       print(ret4)  #[{'publisher__city': '北京'}]
    41       ret5=models.Book.objects.filter(publisher__address='北京').values('publisher__name')
    42       print(ret5)   #[{'publisher__name': '人大出版社'}, {'publisher__name': '人大出版社'}]
    43 
    44       #正向查找(条件)之多对多
    45       ret6=models.Book.objects.filter(title='Python').values('author__name')
    46       print(ret6)
    47       ret7=models.Book.objects.filter(author__name="alex").values('title')
    48       print(ret7)
    49 
    50 # 反向查找(条件)
    51 
    52     #反向查找之一对多:
    53     ret8=models.Publisher.objects.filter(book__title='Python').values('name')
    54     print(ret8)#[{'name': '人大出版社'}]  注意,book__title中的book就是Publisher的关联表名
    55 
    56     ret9=models.Publisher.objects.filter(book__title='Python').values('book__authors')
    57     print(ret9)#[{'book__authors': 1}, {'book__authors': 2}]
    58 
    59     #反向查找之多对多:
    60     ret10=models.Author.objects.filter(book__title='Python').values('name')
    61     print(ret10)#[{'name': 'alex'}, {'name': 'alvin'}]
    View Code
    >>> Publisher.objects.filter(book__price__gt=50).values('book__title')
    <QuerySet [{'book__title': 'python'}, {'book__title': 'php'}, {'book__title': 'C++'}]>

    聚合查询和分组查询:

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

    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出的书总价格                   

           

            查询各个作者出的书的总价格,这里就涉及到分组了,分组条件是authors__name

                

             查询各个出版社最便宜的书价是多少

           

    F查询和Q查询:

     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

    原生SQL的用法:

    http://www.cnblogs.com/lijintian/p/6100097.html 

    附录 Django命令行工具

    django-admin.py 是Django的一个用于管理任务的命令行工具,manage.py是对django-admin.py的简单包装,每一个Django Project里都会有一个mannage.py。

    1 django-admin.py startproject project_name

    创建一个新的django工程。

    2 python manage.py startapp app_name

    创建一个应用。

    3 python manage.py runserver 8080

    启动django项目。

    4 python manage.py makemigrations

    migrations目录下生成同步数据库的脚本。

    同步数据库python manage.py migrate

    5 python manage.py createsuperuser

    创建超级管理员,设置用户名和密码。当我们访问http://http://127.0.0.1:8080/admin/时,便可以通过超级管理员用户登录了。

    6 python manage.py flush

    清空数据库。

    7 django-admin.py help startapp

    查询某个命令的详细信息。

    8 python manage.py shell

    启动交互界面。

    9 python manage.py

    查看django提供的命令。

  • 相关阅读:
    android studio 模拟器控制台发送短信和定位
    android获取超级权限
    android拦截获取别人发送过来的短信
    stackflow看到的获取手机联系人 contact 的代码
    surfaceview绘制矩形 drawRect
    Dialog自定义setView按钮点击没反应
    腾讯移动端性能测试利器PerfDog使用
    Mac下第一个Python程序:HelloWorld
    Mac 系统下安装 PyCharm 的实践
    如何用Chrome浏览器打开Axure原型的start.html文件
  • 原文地址:https://www.cnblogs.com/pyramid1001/p/6089689.html
Copyright © 2011-2022 走看看