• Web框架


    Django框架

     

    一、什么是web框架

       框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演。 对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。

    示例:自己写一个框架

    myWeb.py

    from wsgiref.simple_server import make_server
    
    
    import time
    
    def foo1(req):
        f=open("index2.html","rb")
        data=f.read()
        return data
    
    def foo2(req):
        f=open("index1.html","rb")
        data=f.read()
        return data
    
    def login(req):
        print(req["QUERY_STRING"])
    
        return b"welcome!"
    
    def signup(req):
        pass
    
    def show_time(req):
       times=time.ctime()
    
       #return ("<h1>time:%s</h1>"%str(times)).encode("utf8")
       f=open("show_time.html","rb")
    
       data=f.read()
       data=data.decode("utf8")
       data=data.replace("{{time}}",str(times))
    
       return data.encode("utf8")
    
    def router():
        url_patterns=[
            ("/login",login),
            ("/signup",signup),
            ("/yuan",foo2),
            ("/alex",foo1),
            ("/show_time",show_time),
    
        ]
    
        return url_patterns
    
    def application(environ, start_response):
    
        print("path",environ["PATH_INFO"])
        path=environ["PATH_INFO"]
    
        start_response('200 OK', [('Content-Type', 'text/html')])
    
        url_patterns=router()
    
        func=None
        for item in url_patterns:
            if item[0]==path:
                func=item[1]
                break
        if func:
              return [func(environ)]
        else:
            return [b"404"]
    
    
    httpd = make_server('', 8080, application)
    
    print('Serving HTTP on port 8080...')
    # 开始监听HTTP请求:
    httpd.serve_forever()
    View Code

    show_time.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <script src="jquery-3.1.1.js"></script>
        <title>Title</title>
    
    </head>
    <body>
    
    <h1>时间:{{time}}</h1>
    
    </body>
    </html>
    View Code

    login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <script src="jquery-3.1.1.js"></script>
        <title>Title</title>
    
    </head>
    <body>
    
    
    <form action="http://127.0.0.1:8080/login" method="get">
        <p>用户名<input type="text" name="user"></p>
        <p>密码<input type="password" name="pwd"></p>
        <p><input type="submit">提交</p>
    </form>
    
    </body>
    </html>
    View Code

    index1.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <script src="jquery-3.1.1.js"></script>
        <title>Title</title>
    
    </head>
    <body>
    
    <h1>hello nulige</h1>
    
    </body>
    </html>
    View Code

    index2.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <script src="jquery-3.1.1.js"></script>
        <title>Title</title>
    
    </head>
    <body>
    
    <h1>hello alex</h1>
    
    </body>
    </html>
    View Code

      最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。 如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。 正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口,让我们专心用Python编写Web业务。 这个接口就是WSGI:Web Server Gateway Interface。

    二、MVC和MTV模式

      著名的MVC模式:所谓MVC就是把web应用分为模型(M),控制器(C),视图(V)三层;他们之间以一种插件似的,松耦合的方式连接在一起。

      模型负责业务对象与数据库的对象(ORM),视图负责与用户的交互(页面),控制器(C)接受用户的输入调用模型和视图完成用户的请求。

    Django的MTV模式本质上与MVC模式没有什么差别,也是各组件之间为了保持松耦合关系,只是定义上有些许不同,Django的MTV分别代表:

           Model(模型):负责业务对象与数据库的对象(ORM)

           Template(模版):负责如何把页面展示给用户

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

           此外,Django还有一个url分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template。

    三、django的流程和命令行工具

    django实现流程

    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

    django的命令行工具

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

    <1> 创建一个django工程 : django-admin.py startproject mysite

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

            

    • manage.py ----- Django项目里面的工具,通过它可以调用django shell和数据库等。
    • settings.py ---- 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。
    • urls.py ----- 负责把URL模式映射到应用程序。

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

            

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

           这样我们的django就启动起来了!当我们访问:http://127.0.0.1:8080/时就可以看到:

           

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

                         同步数据库:  python manage.py migrate   

           注意:在开发过程中,数据库同步误操作之后,难免会遇到后面不能同步成功的情况,解决这个问题的一个简单粗暴方法是把migrations目录下

                    的脚本(除__init__.py之外)全部删掉,再把数据库删掉之后创建一个新的数据库,数据库同步操作再重新做一遍。            

    <5>当我们访问http://127.0.0.1:8080/admin/时,会出现:

    所以我们需要为进入这个项目的后台创建超级管理员:python manage.py createsuperuser设置好用户名和密码后便可登录啦!

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

    <7>查询某个命令的详细信息: django-admin.py  help  startapp

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

    <8>启动交互界面 :python manage.py  shell

         这个命令和直接运行 python 进入 shell 的区别是:你可以在这个 shell 里面调用当前项目的 models.py 中的 API,对于操作数据,还有一些小测试非常方便。

    <9> 终端上输入python manage.py 可以看到详细的列表,在忘记子名称的时候特别有用

    实例练习1-提交数据并展示

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

    实例练习2-提交数据并展示(数据库)

    <!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")

    四 Django的配置文件(settings)

    静态文件设置:

    一、概述:
    
         #静态文件交由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:	empmedia,那么File=models.FileField(upload_to="abc/")#,上传的文件就会被保存到c:	empmediaabc  
            #eg:
                class blog(models.Model):  
                       Title=models.charField(max_length=64)  
                       Photo=models.ImageField(upload_to="photo") 
            #     上传的图片就上传到c:	empmediaphoto,而在模板中要显示该文件,则在这样写
            #在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:	empmediaphoto  
                MEDIA_URL="/data/"
            #在开发阶段,media的处理由django处理:
    
            #    访问http://localhost/data/abc/a.png就是访问c:	empmediaphotoabca.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>

    其它重要参数设置:

    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.

    五 Django URL (路由系统)

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

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

    参数说明:

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

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

    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:

    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.

    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.

    5.4 name param

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

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

    综合应用示例:

    新建一个django项目:django_lesson

    代码如下:

    statics下面文件:

    #导入jquery文件

    jquery-3.1.1.js

    blog下面文件:

    urls.py

    from django.conf.urls import url,include
    from django.contrib import admin
    
    #引入模块 from blog import views
    #URL路由分发 urlpatterns = [ url(r'article/(d{4})$',views.article_year), url(r'article/(?P
    <year>d{4})/(?P<month>d{2})',views.article_year_month), url(r'article/(?P<year>d{4})/(?P<month>d{2})/d+',views.article_year_month), url(r"register",views.register,name="reg"), ]

    views.py

    from django.shortcuts import render,HttpResponse
    import time
    # Create your views here. def show_time(requset): #return HttpResponse("hello") t=time.ctime() return render(requset,"index.html",{"time":t})
    def article_year(request,y): return HttpResponse(y)
    def article_year_month(request,year,month): return HttpResponse("year:%s month:%s"%(year,month))
    def register(request): if request.method=="POST": print(request.POST.get("user")) print(request.POST.get("age")) return HttpResponse("success!") return render(request,"register.html")

    diango_lensson下面文件:

    settings.py

    """
    Django settings for django_lesson project.
    
    Generated by 'django-admin startproject' using Django 1.10.5.
    
    For more information on this file, see
    https://docs.djangoproject.com/en/1.10/topics/settings/
    
    For the full list of settings and their values, see
    https://docs.djangoproject.com/en/1.10/ref/settings/
    """
    
    import os
    
    # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    
    # Quick-start development settings - unsuitable for production
    # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/
    
    # SECURITY WARNING: keep the secret key used in production secret!
    SECRET_KEY = '@jm-+mpxpv-@3%=o^fij9w+dtsil=18&6bpt*akkv+=422-vsl'
    
    # SECURITY WARNING: don't run with debug turned on in production!
    DEBUG = True
    
    ALLOWED_HOSTS = []
    
    
    # Application definition
    
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'blog',
    ]
    
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        #'django.middleware.csrf.CsrfViewMiddleware',  #django的安全机制,调试程序请注释掉,否则报错
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    
    ROOT_URLCONF = 'django_lesson.urls'
    
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR, 'templates')]
            ,
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]
    
    WSGI_APPLICATION = 'django_lesson.wsgi.application'
    
    
    # Database
    # https://docs.djangoproject.com/en/1.10/ref/settings/#databases
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }
    
    
    # Password validation
    # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
    
    AUTH_PASSWORD_VALIDATORS = [
        {
            'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
        },
    ]
    
    
    # Internationalization
    # https://docs.djangoproject.com/en/1.10/topics/i18n/
    
    LANGUAGE_CODE = 'en-us'
    
    TIME_ZONE = 'UTC'
    
    USE_I18N = True
    
    USE_L10N = True
    
    USE_TZ = True
    
    
    # Static files (CSS, JavaScript, Images)
    # https://docs.djangoproject.com/en/1.10/howto/static-files/
    
    STATIC_URL = '/static/'  #别名
    
    #配置路径方法一:
    # STATICFILES_DIRS=(
    #     os.path.join(BASE_DIR,"statics"),
    # )
    #配置路径方法二:
    STATICFILES_DIRS=( os.path.join(BASE_DIR,"blog","statics"), )

    urls.py

    """django_lesson URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/1.10/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.conf.urls import url, include
        2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
    """
    from django.conf.urls import url,include
    from django.contrib import admin
    
    #引入模块 from blog import views
    #配置URL路由分发 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^show_time/', views.show_time), url(r'^blog/', include('blog.urls')), ]

    templates下面文件:

    register.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        {% load staticfiles %}
        <meta charset="UTF-8">
        <script src="jquery-3.1.1.js"></script>
        <title>Title</title>
    
        <style>
            * {
                margin: 0;
                padding: 0
            }
    
    
        </style>
    </head>
    <body>
    
    <h1>学生注册</h1>
    <hr>
    <form action="{% url 'reg' %}" method="post">
       <p>姓名<input type="text" name="user"></p>
       <p>年龄<input type="text" name="age"></p>
       <p>爱好<input type="checkbox" name="hobby" value="1">篮球
              <input type="checkbox" name="hobby" value="2">足球
              <input type="checkbox" name="hobby" value="3">乒乓球
       </p>
       <p><input type="submit">提交</p>
    </form>

    </body> </html>

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        {% load staticfiles %}
        <title>Title</title>
    
        <style>
            * {
                margin: 0;
                padding: 0
            }
    
        </style>
    </head>
    <body>
    
    <h1>hello {{ time }}</h1>
    
    //<script src="/static/jquery-3.1.1.js"></script>
    <script src="{% static 'jquery-3.1.1.js' %}"></script>
    
    
    <script>
        $("h1").css("color","red")
    </script>
    
    
    </body>
    </html>

    六 Django Views(视图函数)

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

            http请求:HttpRequest对象

            http响应:HttpResponse对象

    所在位置:django.http

    之前我们用到的参数request就是HttpRequest    检测方法:isinstance(request,HttpRequest)

    1 HttpRequest对象的属性和方法:

    # 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

    注意一个常用方法:request.POST.getlist('')

    2 HttpResponse对象:

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

      HttpResponse类在django.http.HttpResponse

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

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

    补充:

    -----------------------------------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/,所以当刷新后
    #     又得重新登录.

    七 Template基础 

    模板系统介绍

    模板系统的组成:HTML代码和逻辑控制代码

    逻辑控制代码可以理解是django模板语言

    django的模板语言组成

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

    2. 标签(tag)的使用(使用大括号和百分比的组合来表示使用tag)
    3. 模板继承

    模板语言之变量

    语法:

    1
    {{var_name}}   var_name 指变量名

      

    使用模板语言之前:

    先介绍template对象和Context对象

    进入django的项目的交互环境

    1
    2
    3
    4
    5
    6
    7
    python manange.py shell
     
    >>> from django.template import Context, Template
    >>> t = Template('My name is {{ name }}.')   #模板对象
    >>> c = Context({'name''xixi'})       #上下文对象
    >>> t.render(c)
    'My name is xixi.'

      

    同一模板,多个上下文,一旦有了模板对象,你就可以通过它渲染多个context,无论何时我们都可以像这样使用同一模板源渲染多个context,只进行 一次模板创建然后多次调用render()方法渲染会更为高效:

    模板对象:可以理解文HTML文件,只不过包含了Django的模板语法

    context对象:大多数的情况下,我们会将字典传给Context(),一旦初始化后,就可以使用标准的Python字典语法操作Context对象:

    上下文对象如果是不合法的变量,模板系统会把他当做空字符串显示

    1
    2
    3
    >>> t = Template('Your name is {{  name }}')   变量名是name
    >>> t.render(Context({'var':'hello'}))  #没有var这个变量名字
    'Your name is '

    变量之深度查询(英文句点符.)

    上面只是通过 context 传递的简单参数值主要是字符串,然而,模板系统能够非常简洁地处理更加复杂的数据结构,例如list、dictionary和自定义的对象。

    list索引

    1
    2
    3
    4
    5
    6
    >>> from django.template import Context, Template
    >>> names = ["xixi","abc","123","hehe"]
    >>> t = Template("this is {{ name.0}}")
    >>> c = Context({"name":names})
    >>> t.render(c)
    'this is xixi'

    如果不写 {{ name.0}}  后面的(.索引) 表示整个列表

    字典

    1
    2
    3
    4
    5
    6
    >>> from  django.template  import  Template, Context
    >>> person = {'name':"xixi""age": 21}
    >>> t = Template("{{ person.name }} is {{ person.age }} years old.")
    >>> c = Context({ "person": person })
    >>> t.render(c)
    'xixi is 25 years old.'

    自定义对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    >>> from   django.template  import  Template, Context
    >>> import  datetime
    >>> d = datetime.date(1996, 12,12 )
    >>> d.year
    1996
    >>> d.month
    12
    >>> d.day
    12
    >>> t = Template('The month is {{ date.month }} and year is {{ date.year }}')
    >>> c = Context({'date': d})
    >>> t.render(c)
    'The month is 12 and year is 1996' 

    访问对象方法

    1
    2
    3
    4
    5
    >>> t = Template('{{ var }} -- {{ var.upper }} -- {{  var.isdigit }}')
    >>> t.render(Context({'var''hello'}))
    'hello -- HELLO -- False'
    >>> t.render(Context({'var''123'}))
    '123 -- 123 -- True'

    跟python操作差不多 

    变量过滤器(filter)的使用

    语法格式

    1
    {{var|filter:param}}

    管道符号后面的功能,比如{{ var|length }},求变量长度的 length 就是一个过滤器。

    常用的过滤器

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

    标签(tag)的使用

    语法格式

    1
    {% tags %}

    {% if %} 的使用

    {% if %} 和 {% endif %}要成对

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    {% 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 %}   

     {% for %}的使用

    {% for %} 和 {% endfor %}要成对

    {% for %}标签允许你按顺序遍历一个序列中的各个元素,每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容

    1
    2
    3
    4
    5
    6
    基本格式
    <ul>
    {% for obj in list %}
        <li>{{ obj.name }}</li>
    {% endfor %}
    </ul> 

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

    1
    2
    3
    {% for obj in list reversed %}
        ...
    {% endfor %} 

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

    1
    2
    3
    4
    5
    6
    7
    8
    {% for country in countries %}
            <h1>{{ country.name }}</h1>
            <ul>
             {% for city in country.city_list %}
                <li>{{ city }}</li>
             {% endfor %}
            </ul>
    {% endfor %}

    {% for %}不支持中断循环,也不支持continue语句

    {% for %}关于循环其他用法

    1
    2
    3
    4
    5
    6
    7
    forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1:
    forloop.counter0    索引从 0 开始算
    forloop.revcounter表示循环中剩下的items数量,第一次循环时设为items总数,最后一次设为1
    forloop.revcounter0表示`items总数少一个,最后一次循环设置为0
    forloop.first表示当第一次循环时值为True,在特别情况下很有用:
    forloop.last表示当最后一次循环时值为True
    forloop。parentioop表示在嵌套循环中表示父级循环的forloop

      

    富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了

    如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它

    Django会在for标签的块中覆盖你定义的forloop变量的值

    在其他非循环的地方,你的forloop变量仍然可用

    1
    2
    3
    4
    {% for item in todo_list %}
            <p>{{ forloop.counter }}: {{ item }}</p>
    {% endfor %}
    表示循环的次数,它从1开始计数,第一次循环设为1:

    {%csrf_token%}:csrf_token标签

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

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

    1
    2
    3
    4
    5
    <form action="{% url "路由别名"%}" >
              <input type="text">
              <input type="submit"value="提交">
              {%csrf_token%}
    </form>

    {% with %}:用更简单的变量名替代复杂的变量名

    1
    2
    {% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}
    基本很少起复杂变量名,一般起变量名都要特变形象

    {% verbatim %}: 禁止render渲染

    1
    2
    3
    4
    5
    6
    {% verbatim %}
             {{ hello }}
    {% endverbatim %
     
     
    如果想要{{hello}}在网页正常显示出来,则用这个

    {% load %}: 加载标签库 

    静态文件的引入方式用过

    {% load  staticfiles %}

    后面引入其他的标签库在一一列出

    自定义filter和simple_tag

    我们自定义过滤器和简单的标签我们需要

    1. 在app中创建templatetags文件夹(文件夹名字必须的是这个)
    2. 创建任意 .py 文件,如:my_tags.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    from django import template
    from django.utils.safestring import mark_safe
    register = template.Library()  #register的名字是固定的,不可改变
     
    @register.filter
    def filter_multi(x,y):
        return x*y
     
    @register.simple_tag
    def simple_tag_multi(x,y):
        return x*y
     
    @register.simple_tag
    def my_input(id,arg):
        result = "<input type='text' id='%s' class='%s' />" %(id,arg)
        return mark_safe(result)

      

    如何调用自定义filter和simple_tag

    在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py :{% load my_tags %}

    在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    {% load my_tags %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    {{ num|filter_multi:2 }} #24 <br>
     
    {{ num|filter_multi:"[22,333,4444]" }}<br>
     
     
    <p>{% simple_tag_multi 2 5 %}  参数不限,但不能放在if for语句中 </p>
    {% simple_tag_multi num 5 %}
     
    </body>
    </html>

      

    视图和路由的配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #路由
    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
     
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^index/',views.index),
    ]
     
     
    #视图
     
    from django.shortcuts import render,HttpResponse
     
    # Create your views here.
    def index(request):
     
        num=12
        return  render(request,"index.html",locals()) 

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

    模板引入和继承

    模板引入

     {% include %}该标签允许在(模板中)包含其它的模板的内容。 标签的参数是所要包含的模板名称,可以是一个变量,也可以是用单/双引号硬编码的字符串。 每当在多个模板中出现相同的代码时,就应该考虑是否要使用 {% include %} 来减少重复。

    引入方法

    1
    2
    3
    4
    5
    6
    {% load staticfiles %}
     
    HTML相关内容
     
     
    {% include '要引入的html文件名' %}

      

    模板继承

    常见的 Web 开发问题: 在整个网站中,如何减少共用页面区域(比如站点导航)所引起的重复和冗余代码?

    解决该问题的传统做法是使用 服务器端的 includes ,你可以在 HTML 页面中使用该指令将一个网页嵌入到另一个中。 事实上, Django 通过刚才讲述的 {% include %} 支持了这种方法。 但是用 Django 解决此类问题的首选方法是使用更加优雅的策略—— 模板继承 。

    本质上来说,模板继承就是先构造一个基础框架模板,而后在其子模板中对它所包含站点公用部分和定义块进行重载。

    如果子板不自定义块,默认会继承母板的所有内容(包括模板的css,js),如果子板要修改css或js文件,在相应地方加块,就可以了

    例如:

    简单写一个子板继承母板

    定义母板文件base.html,定义子板要自定义的块

      

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
     
    <H1> HAHA </H1>
     
    {% block  content %}
        <h2>子板自定义修改的内容</h2>
     
    {% endblock %}
    </body>
    </html>

      

    定义子板文件child.html

    1
    {% extends "base.html" %}

      

    子板如果就这么一行代码,就会继承母板的所有内容,这{% extends "母板文件" %}必须写在最首行

    如果要自定义修改块

    1
    2
    3
    4
    {% extends "base.html" %}
    {% block content %}
        <h2 style="color: red">我是子板,修改了母板自定义块的内容</h2>
    {% endblock %}

      

    注:

    母板

    {% block 自定义块名%}   

    子板的块

    {% block 母板中相应设置的块名 }

    {% block %}  内容 {% endblock %}的标签也是成对出现

    使用继承的注意事项:

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

    模板继承的一些诀窍:

      1. 如果在模板中使用 {% extends %} ,必须保证其为模板中的第一个模板标记。 否则,模板继承将不起作用。
      2. 一般来说,基础模板中的 {% block %} 标签越多越好。 记住,子模板不必定义父模板中所有的代码块,因此你可以用合理的缺省值对一些代码块进行填充,然后只对子模板所需的代码块进行(重)定义。 俗话说,钩子越多越好。
      3. 如果发觉自己在多个模板之间拷贝代码,你应该考虑将该代码段放置到父模板的某个 {% block %} 中。如果你需要访问父模板中的块的内容,使用 {{ block.super }}这个标签吧,这一个魔法变量将会表现出父模板中的内容。 如果只想在上级代码块基础上添加内容,而不是全部重载,该变量就显得非常有用了。
      4. 不允许在同一个模板中定义多个同名的 {% block %} 。 存在这样的限制是因为block 标签的工作方式是双向的。也就是说,block 标签不仅挖了一个要填的坑,也定义了在父模板中这个坑所填充的内容。如果模板中出现了两个相同名称的 {% block %} 标签,父模板将无从得知要使用哪个块的内容。

    八 Models

    数据库的配置

    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里有如下设置:

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

    如果我们想要更改数据库,需要修改如下:

               

    注意:

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

    4、通过ORM连接数据库,参考我的另外一篇博文

    地址:http://www.cnblogs.com/nulige/p/6484772.html

     语法:

    DATABASES = {
    
        'default': {
    
            'ENGINE': 'django.db.backends.mysql',
    
            'NAME': 'Django_ORM',    #你的数据库名称
    
            'USER': 'root',   #你的数据库用户名
    
            'PASSWORD': '123456', #你的数据库密码
    
            'HOST': '', #你的数据库主机,留空默认为localhost
    
            'PORT': '3306', #你的数据库端口
        }}

    显示调试信息

    在settings.py中加入这段代码:

    #加在任意位置
    
    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console':{
                'level':'DEBUG',
                'class':'logging.StreamHandler',
            },
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'propagate': True,
                'level':'DEBUG',
            },
        }
    }

    ORM(对象关系映射)

    SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。

      SQLAlchemy本身无法操作数据库,其必须以来pymsql等第三方插件,Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作。

      用于实现面向对象编程语言里不同类型系统的数据之间的转换,换言之,就是用面向对象的方式去操作数据库的创建表以及增删改查等操作。

    优点: 1 ORM使得我们的通用数据库交互变得简单易行,而且完全不用考虑该死的SQL语句。快速开发,由此而来。

    缺点:

    1  性能有所牺牲,不过现在的各种ORM框架都在尝试各种方法,比如缓存,延迟加载登来减轻这个问题。效果很显著。

    2  对于个别复杂查询,ORM仍然力不从心,为了解决这个问题,ORM一般也支持写raw sql。

    3  通过QuerySet的query属性查询对应操作的sql语句

    模型之间的三种关系:一对一,一对多,多对多。

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

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

                 多对多:(ManyToManyField) 自动创建第三张表(当然我们也可以自己创建第三张表:两个foreign key)

     模型常用的字段类型参数

    <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参数.

    Field重要参数

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

    表的操作

    表记录的添加

    方式一:
    b=Book(name="python基础",price=99,author="yuan",pub_date="2017-12-12")
    b.save()
    
    方式二:
    Book.objects.create(name="老男孩linux",price=78,author="oldboy",pub_date="2016-12-12")

    表记录的修改

    方式一:
    b=Book.objects.get(author="oldboy")
    b.price=120
    b.save()
    
    方式二:
    Book.objects.filter(author="yuan").update(price=999)

    表记录的删除

    Book.objects.filter(author="oldboy").delete()

    表记录的查询(filter,value)

    查询API

    # 查询相关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。

    补充:

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

    惰性机制:

    所谓惰性机制:Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它并不会马上执行sql,而是当调用QuerySet的时候才执行。

    QuerySet特点:

           <1>  可迭代的

           <2>  可切片

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

    QuerySet的高效使用:

    <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,可能会造成额外的数据库查询。

    对象查询,单表条件查询,多表条件关联查询

    #--------------------对象形式的查找--------------------------
        # 正向查找
        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
        #一对多和多对多在这里用法没区别

    注意:条件查询即与对象查询对应,是指在filter,values等方法中的通过__来明确查询条件。

    综合应用示例:

    Diango_ORM--->urls.py

    from django.conf.urls import url
    from django.contrib import admin
    
    #导入相关模块
    from app01 import views
    
    
    #配置路由分发
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^index/', views.index),
        url(r'^addbook/', views.addbook),
        url(r'^update/', views.update),
        url(r'^delete/', views.delete),
    
    ]

    settings.py

    """
    Django settings for Django_ORM project.
    
    Generated by 'django-admin startproject' using Django 1.10.5.
    
    For more information on this file, see
    https://docs.djangoproject.com/en/1.10/topics/settings/
    
    For the full list of settings and their values, see
    https://docs.djangoproject.com/en/1.10/ref/settings/
    """
    
    import os
    
    # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    
    # Quick-start development settings - unsuitable for production
    # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/
    
    # SECURITY WARNING: keep the secret key used in production secret!
    SECRET_KEY = 'i464n)l3a$wqvpk9t7lol-7jjg9bb-()v6go0hwgka7!=9+pl%'
    
    # SECURITY WARNING: don't run with debug turned on in production!
    DEBUG = True
    
    ALLOWED_HOSTS = []
    
    
    # Application definition
    
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'app01',
    ]
    
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    
    ROOT_URLCONF = 'Django_ORM.urls'
    
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR, 'templates')]
            ,
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]
    
    WSGI_APPLICATION = 'Django_ORM.wsgi.application'
    
    
    # Database
    # https://docs.djangoproject.com/en/1.10/ref/settings/#databases
    
    # DATABASES = {
    #     'default': {
    #         'ENGINE': 'django.db.backends.sqlite3',
    #         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    #     }
    # }
    
    #连接数据库
    DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django_orm', 'USER': 'root', 'PASSWORD': 'oldboy123', 'HOST': '', 'PORT': '3306', } }
    # Password validation # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/1.10/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.10/howto/static-files/ STATIC_URL = '/static/' #显示调试信息 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }

    app01--->models.py

    from django.db import models
    
    # Create your models here.
    
    
    # class Book(models.Model):
    #     name=models.CharField(max_length=20)
    #     price=models.IntegerField()
    #     pub_date=models.DateField()
    
    
    #创建表
    class Book(models.Model):
        name=models.CharField(max_length=20)
        price=models.IntegerField()
        pub_date=models.DateField()
        author=models.CharField(max_length=32,null=False)

    templates--->index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <script src="jquery-3.1.1.js"></script>
        <title>Title</title>
    
        <style>
            * {
                margin: 0;
                padding: 0
            }
            .head{
                line-height: 40px;
                background-color: green;
                color: white;
                text-align: center;
    
            }
    
        </style>
    </head>
    <body>
    
    <div class="outer">
        <div class="head">标题</div>
        <div class="content">
            <a href="/addbook/">添加书籍</a>
            <a href="/update/">修改书籍</a>
            <a href="/delete/">删除书籍</a>
        </div>
    </div>
    
    </body>
    </html>
    View Code

    views.py

    from django.shortcuts import render,HttpResponse
    
    # Create your views here.
    from app01.models import *
    
    def index(request):
    
        return render(request,"index.html")
    
    def addbook(request):
    
        # b=Book(name="python基础",price=99,author="yuan",pub_date="2017-12-12")
        # b.save()
        Book.objects.create(name="老男孩linux",price=78,author="oldboy",pub_date="2016-12-12")
        #Book.objects.create(**dic)
    
        return HttpResponse("添加成功")
    
    
    def update(request):
    
        Book.objects.filter(author="yuan").update(price=999)
    
        # b=Book.objects.get(author="oldboy")
        # b.price=120
        # b.save()
        # print(b)#<QuerySet [<Book: Book object>]>
        # print(type(b))
    
        return HttpResponse("修改成功!")
    
    
    def delete(req):
    
        Book.objects.filter(author="oldboy").delete()
    
        return HttpResponse("success")
    
    def select(req):
        book_list=Book.objects.all()
        print(book_list)
        print(book_list[0])#Book object

    book_list = Book.objects.filter(id=2)
    book_list
    = Book.objects.all()[::2] book_list = Book.objects.all()[::-1] book_list = Book.objects.first() book_list = Book.objects.last() book_list = Book.objects.get(id=2)#只能取出一条记录时才不报错 ret1=Book.objects.filter(author="oldboy").values("name") ret2=Book.objects.filter(author="yuan").values_list("name","price") book_list=Book.objects.exclude(author="yuan").values("name","price") print(ret1) print(ret2) book_list= Book.objects.all().values("name").distinct() book_count= Book.objects.all().values("name").distinct().count() print(book_count) #万能的 __ book_list=Book.objects.filter(price__gt=50).values("name","price") book_list=Book.objects.filter(name__contains="P").values_list("name","price") return render(req,"index.html",{"book_list":book_list})

     增加改查的时候,刷新网页,写入数据库中

    单表操作总结:

    单表操作
    
            表记录的添加
                 
            方式一:
                Book()
                b=Book(name="python基础",price=99,author="yuan",pub_date="2017-12-12")
                b.save()
                方式二:
                Book.objects.create()
                Book.objects.create(name="老男孩linux",price=78,author="oldboy",pub_date="2016-12-12")
    
    
            表记录的修改
                方式一:
                
                b=Book.objects.get(author="oldboy")
                b.price=120
                b.save()
                
                方式二:(推荐方法)
                #update是QuerySet
                Book.objects.filter(author="yuan").update(price=999)
             
            表记录的删除:
                Book.objects.filter(author="oldboy").delete()
                
            表记录的查询(重点):
            
                    book_list = Book.objects.filter(id=2)
                    book_list=Book.objects.exclude(author="yuan").values("name","price")   
    
    
                    book_list=Book.objects.all()
                    book_list = Book.objects.all()[::2]
                    book_list = Book.objects.all()[::-1]
               
                    #first,last,get取到的是一个实例对象,并非一个QuerySet的集合对象
                    book_list = Book.objects.first()
                    book_list = Book.objects.last()  
                    book_list = Book.objects.get(id=2)#只能取出一条记录时才不报错
    
                    #返回字典的类型记录值
                    ret1=Book.objects.filter(author="oldboy").values("name")
    
            #集合里面显示元组的方式返回值
                    ret2=Book.objects.filter(author="yuan").values_list("name","price")
                
            #distinct方法去重
                    book_list= Book.objects.all().values("name").distinct()
                    book_count= Book.objects.all().values("name").distinct().count()
                   
                
                    模糊匹配查询 使用:双下划线__
                    book_list=Book.objects.filter(name__icontains="P").values_list("name","price")
                    
            #>5的记录筛选出来
            book_list=Book.objects.filter(id__gt=5).values_list("name","price")
                    
     
          多表操作(一对多):
                   #添加记录
                   #publish_id=2
                   Book.objects.create(name="linux运维",price=77,pub_date="2017-12-12",publish_id=2)
                   
    
                   #publish=object
                   Book.objects.create(name="GO",price=23,pub_date="2017-05-12",publish=publish_obj)
                   
                   #查询记录(通过对象)
                         正向查询:
                         book_obj=Book.objects.get(name="python")   
                         pub_obj=book_obj.publish----》书籍对象对应的出版社对象
                         pub_obj.name
    
                         反向查询:
                         pub_obj = Publish.objects.filter(name="人民出版社")[0]
                         pub_obj.book_set.all().values("name","price")
    
        #查询记录 (filter values  双下划线__)
            #人民出版社出版过的书籍与价格
            ret=Book.objects.filter(publish__name="人民出版社").values("name","price")
            
            #python这本书出版社的名字
            ret2=Publish.objects.filter(book_name=“python”).values("name")
    
            #python这本书出版社的名字
            ret3=Book.object.filter(name="python").values("publish__name")
    
            #北京的出版社出版书的名字
            ret4=Book.objects.filter(publish__city="北京").values("name")
    
            #2017年上半年出版过书的出版社的名字
            ret5=Book.objects.filter(pub_date__lt="2017-07-01",pub_date__gt="2017-01-01").values("name")

    示例:

    views.py

    from django.shortcuts import render,HttpResponse
    from django.db.models import Avg,Min,Sum,Max,Count
    from django.db.models import Q,F
    # Create your views here.
    from app01.models import *
    
    def index(request):
    
    
        return render(request,"index.html")
    
    def addbook(request):
    
        # Book.objects.create(name="linux运维",price=77,pub_date="2017-12-12",publish_id=2)
    
        #publish_obj=Publish.objects.filter(name="人民出版社")[0]
        #Book.objects.create(name="GO",price=23,pub_date="2017-05-12",publish=publish_obj)
    
        # book_obj=Book.objects.get(name="python")
        # print(book_obj.name)
        # print(book_obj.pub_date)
        #
        # #一对多:book_obj.publish--------一定是一个对象
        # print(book_obj.publish.name)
        # print(book_obj.publish.city)
        # print(type(book_obj.publish))
    
    
        #查询人民出版社出过的所有书籍名字和价格
        #方式一:
        # pub_obj=Publish.objects.filter(name="人民出版社")[0]
        # ret=Book.objects.filter(publish=pub_obj).values("name","price")
        # print(ret)
    
        #方式二
        # pub_obj = Publish.objects.filter(name="人民出版社")[0]
        # print(pub_obj.book_set.all().values("name","price"))
        #print(type(pub_obj.book_set.all()))
    
        #方式三
        # ret=Book.objects.filter(publish__name="人民出版社").values("name","price")
        # print(ret)
        #
        # python这本书出版社的名字
        # ret2=Publish.objects.filter(book__name="python").values("name")
        # print(ret2)
        # ret3=Book.objects.filter(name="python").values("publish__name")
        # print(ret3)
        #
        # ret4=Book.objects.filter(publish__city="北京").values("name")
        # print(ret4)
        #
        # ret5=Book.objects.filter(pub_date__lt="2017-07-01",pub_date__gt="2017-01-01").values("publish__name")
        # print(ret5)
    
        #通过对象的方式绑定关系
    
    
        # book_obj=Book.objects.get(id=3)
        # print(book_obj.authors.all())
        # print(type(book_obj.authors.all()))
        #
        # author_obj=Author.objects.get(id=2)
        # print(author_obj.book_set.all())
    
        # book_obj=Book.objects.get(id=3)
        # author_objs=Author.objects.all()
        # #book_obj.authors.add(*author_objs)
        # # book_obj.authors.remove(*author_objs)
        # book_obj.authors.remove(4)
    
    
        #创建第三张表
        # Book_Author.objects.create(book_id=2,author_id=2)
        #
        # obj=Book.objects.get(id=2)
        # print(obj.book_author_set.all()[0].author)
    
        #alex出过的书籍名称及价格
    
        # ret=Book.objects.filter(book_author__author__name="alex").values("name","price")
        # print(ret)
    
        # ret2=Book.objects.filter(authors__name="alex").values("name","price","authors__name")
        # print(ret2)
    
        # ret=Book.objects.all().aggregate(Avg("price"))
        # ret=Book.objects.all().aggregate(Sum("price"))
        # ret=Book.objects.filter(authors__name="alex").aggregate(alex_money=Sum("price"))
        # ret=Book.objects.filter(authors__name="alex").aggregate(Count("price"))
        # print(ret)
    
        # ret=Book.objects.values("authors__name").annotate(Sum("price"))
        # print(ret)
    
        # ret=Publish.objects.values("name").annotate(abc=Min("book__price"))
        # print(ret)
    
    
        # b=Book.objects.get(name="GO",price=77)
        # print(b)
    
        #Book.objects.all().update(price=F("price")+10)
    
        # ret=Book.objects.filter(Q(name__contains="G"))
        # print(ret)
    
        # ret=Book.objects.filter(Q(name="GO"),price=87)
        # print(ret)
    
        #ret=Book.objects.filter(price=200)
    
        # for i in ret:
        #     print(i.price)
        #
        # Book.objects.all().update(price=200)
        # ret = Book.objects.filter(price=100)
        # for i in ret:
        #     print(i.price)
    
    
        # if ret.exists():
        #     print("ok")
    
        # ret=ret.iterator()
        # print(ret)
        #
        # for i in ret:
        #     print(i.name)
        #
        # for i in ret:
        #     print(i.name)
    
    
        return HttpResponse("添加成功")
    
    def update():pass
    def delete():pass
    def select():pass

    models.py

    from django.db import models
    
    # Create your models here.
    
    
    class Book(models.Model):
        name=models.CharField(max_length=20)
        price=models.IntegerField()
        pub_date=models.DateField()
        publish=models.ForeignKey("Publish")
        authors=models.ManyToManyField("Author")
    
        def __str__(self):
            return self.name
    
    class Publish(models.Model):
    
        name=models.CharField(max_length=32)
        city=models.CharField(max_length=32)
    
        def __str__(self):
            return self.name
    
    
    # class Book_Author(models.Model):
    #     book=models.ForeignKey("Book")
    #     author=models.ForeignKey("Author")
    
    
    class Author(models.Model):
    
        name=models.CharField(max_length=32)
        age=models.IntegerField(default=20)
    
        def __str__(self):
            return self.name

    urls.py

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <script src="jquery-3.1.1.js"></script>
        <title>Title</title>
    
        <style>
            * {
                margin: 0;
                padding: 0
            }
            .head{
                line-height: 40px;
                background-color: green;
                color: white;
                text-align: center;
    
            }
    
        </style>
    </head>
    <body>
    
    <div class="outer">
        <div class="head">标题</div>
        <div class="content">
            <a href="/addbook/">添加书籍</a>
            <a href="/update/">修改书籍</a>
            <a href="/delete/">删除书籍</a>
            <a href="/select/">查询书籍</a>
        </div>
        <hr>
        <div class="queryResult">
             {% for book in book_list %}
             <div>
                  <p>{{ book.name }} {{ book.author }} {{ book.price }}</p>
             </div>
             {% endfor %}
        </div>
    </div>
    
    </body>
    </html>

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <script src="jquery-3.1.1.js"></script>
        <title>Title</title>
    
        <style>
            * {
                margin: 0;
                padding: 0
            }
            .head{
                line-height: 40px;
                background-color: green;
                color: white;
                text-align: center;
    
            }
    
        </style>
    </head>
    <body>
    
    <div class="outer">
        <div class="head">标题</div>
        <div class="content">
            <a href="/addbook/">添加书籍</a>
            <a href="/update/">修改书籍</a>
            <a href="/delete/">删除书籍</a>
            <a href="/select/">查询书籍</a>
        </div>
        <hr>
        <div class="queryResult">
             {% for book in book_list %}
             <div>
                  <p>{{ book.name }} {{ book.author }} {{ book.price }}</p>
             </div>
             {% endfor %}
        </div>
    </div>
    
    </body>
    </html>

    聚合查询和分组查询

    示例:

    models.py (建表语句)

    from django.db import models
    
    # Create your models here.
    
    
    class Book(models.Model):
        name=models.CharField(max_length=20)
        price=models.IntegerField()
        pub_date=models.DateField()
        publish=models.ForeignKey("Publish")
        authors=models.ManyToManyField("Author")
    
        def __str__(self):
            return self.name
    
    class Publish(models.Model):
    
        name=models.CharField(max_length=32)
        city=models.CharField(max_length=32)
    
        def __str__(self):
            return self.name
    
    
    # class Book_Author(models.Model):
    #     book=models.ForeignKey("Book")
    #     author=models.ForeignKey("Author")
    
    
    class Author(models.Model):
    
        name=models.CharField(max_length=32)
        age=models.IntegerField(default=20)
    
        def __str__(self):
            return self.name

    views.py

    from django.shortcuts import render,HttpResponse
    from django.db.models import Avg,Min,Sum,Max,Count
    
    # Create your views here.
    from app01.models import *
    
    def index(request):
    
    
        return render(request,"index.html")
    
    def addbook(request):
    
        # Book.objects.create(name="linux运维",price=77,pub_date="2017-12-12",publish_id=2)
    
        #publish_obj=Publish.objects.filter(name="人民出版社")[0]
        #Book.objects.create(name="GO",price=23,pub_date="2017-05-12",publish=publish_obj)
    
        # book_obj=Book.objects.get(name="python")
        # print(book_obj.name)
        # print(book_obj.pub_date)
        #
        # #一对多:book_obj.publish--------一定是一个对象
        # print(book_obj.publish.name)
        # print(book_obj.publish.city)
        # print(type(book_obj.publish))
    
    
        #查询人民出版社出过的所有书籍名字和价格
        #方式一:
        # pub_obj=Publish.objects.filter(name="人民出版社")[0]
        # ret=Book.objects.filter(publish=pub_obj).values("name","price")
        # print(ret)
    
        #方式二
        # pub_obj = Publish.objects.filter(name="人民出版社")[0]
        # print(pub_obj.book_set.all().values("name","price"))
        #print(type(pub_obj.book_set.all()))
    
        #方式三
        # ret=Book.objects.filter(publish__name="人民出版社").values("name","price")
        # print(ret)
        #
        # python这本书出版社的名字
        # ret2=Publish.objects.filter(book__name="python").values("name")
        # print(ret2)
        # ret3=Book.objects.filter(name="python").values("publish__name")
        # print(ret3)
        #
        # ret4=Book.objects.filter(publish__city="北京").values("name")
        # print(ret4)
        #
        # ret5=Book.objects.filter(pub_date__lt="2017-07-01",pub_date__gt="2017-01-01").values("publish__name")
        # print(ret5)
    
        #通过对象的方式绑定关系
    
    
        # book_obj=Book.objects.get(id=3)
        # print(book_obj.authors.all())
        # print(type(book_obj.authors.all()))
        #
        # author_obj=Author.objects.get(id=2)
        # print(author_obj.book_set.all())
    
    
        # book_obj=Book.objects.get(id=3)
        # author_objs=Author.objects.all()
        # #book_obj.authors.add(*author_objs)
        # # book_obj.authors.remove(*author_objs)
        # book_obj.authors.remove(4)
    
        #创建第三张表
        # Book_Author.objects.create(book_id=2,author_id=2)
        #
        # obj=Book.objects.get(id=2)
        # print(obj.book_author_set.all()[0].author)
    
        #alex出过的书籍名称及价格
    
        # ret=Book.objects.filter(book_author__author__name="alex").values("name","price")
        # print(ret)
    
        # ret2=Book.objects.filter(authors__name="alex").values("name","price","authors__name")
        # print(ret2)
    
        # ret=Book.objects.all().aggregate(Avg("price"))
        # ret=Book.objects.all().aggregate(Sum("price"))
        # ret=Book.objects.filter(authors__name="alex").aggregate(alex_money=Sum("price"))
        # ret=Book.objects.filter(authors__name="alex").aggregate(Count("price"))
        # print(ret)
    
        # ret=Book.objects.values("authors__name").annotate(Sum("price"))
        # print(ret)
    
        # ret=Publish.objects.values("name").annotate(abc=Min("book__price"))
        # print(ret)
    
        return HttpResponse("添加成功")
    
    def update():pass
    def delete():pass
    def select():pass
    

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <script src="jquery-3.1.1.js"></script>
        <title>Title</title>
    
        <style>
            * {
                margin: 0;
                padding: 0
            }
            .head{
                line-height: 40px;
                background-color: green;
                color: white;
                text-align: center;
    
            }
    
        </style>
    </head>
    <body>
    
    <div class="outer">
        <div class="head">标题</div>
        <div class="content">
            <a href="/addbook/">添加书籍</a>
            <a href="/update/">修改书籍</a>
            <a href="/delete/">删除书籍</a>
            <a href="/select/">查询书籍</a>
        </div>
        <hr>
        <div class="queryResult">
             {% for book in book_list %}
             <div>
                  <p>{{ book.name }} {{ book.author }} {{ book.price }}</p>
             </div>
             {% endfor %}
        </div>
    </div>
    
    </body>
    </html>
    

    urls.py

    """ORM_multi URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/1.10/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.conf.urls import url, include
        2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
    """
    from django.conf.urls import url
    from django.contrib import admin
    
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^index/', views.index),
        url(r'^addbook/', views.addbook),
        url(r'^update/', views.update),
        url(r'^delete/', views.delete),
        url(r'^select/', views.delete),
    ]
    
  • 相关阅读:
    linux自动清理30天之前的文件
    Oracle树查询及相关函数
    jackson循环引用导致序列化stackOverFlow的解决
    java核心技术36讲笔记
    Quartz学习
    Quartz学习
    java核心技术36讲
    git常用命令
    CTCall简介(后续会继续补充)
    自定义导航栏,隐藏导航栏底部的灰色线条
  • 原文地址:https://www.cnblogs.com/honglingjin/p/6508640.html
Copyright © 2020-2023  润新知