web框架-Django(简介,请求基本周期、路由层、视图函数、模板层、模型层,CBV&FBV)

Django简介基本使用项目创建于app创建请求执行的周期(基本)路由系统视图函数模板层模型层

参考网址,https://www.cnblogs.com/clschao/articles/10526431.html 

 

 

Django简介

 

  • pip安装,配置环境变量 ……python\script                     django-admin

创建、操作django项目:

  • 创建工程项目
    • 方式一:cmd命令行     django-admin startproject 项目名
    • 方式二:IDE,pycharm中创建django项目
      • 在使用pycharm过程中,需要设置django server:
        • 名字是项目名字
        • 默认ip,端口
        • environment variable:      DJANGO_SETTINGS_MODULE 工程项目名.settings               PYTHONUNBUFFERED : 1
        • python解释器
    • 运行:
      • 命令行中,  python    manage.py runserver  指定host:端口        host和端口可省略,使用默认
      • pycharm中完成配置。   在“select run /debug configuration” 中选定配置好的django ,点击运行   
  • django项目目录结构:
    • 与项目同名的文件夹     :完成程序的整体配置
    • init
    • settings                    :配置文件
      • TEMPLATES  进行模板文件配置,设置模板文件的查找路径等。
      • STATIC_URL    静态路径
      • STATICFILES_DIRS  静态文件路径配置,设置css,js等静态文件路径信息
    • urls                      :url对应关系
    • wsji            :wsgi规范
    • manage.py     :管理django程序
      • python manage.py 运行
      • python manage.py startapp  程序名
      • python manage.py  makemigrations
      • python manage.py migrate  
  •  创建app
    • 在cmd命令行中,进入工程项目目录,  python manage.py startapp  指定app名
    • windows python中可通过 Teminal 运行上面的命令
    • 常见app   :cmdb  templates  openstack……
    • app内部结构文件功能(cmdb):
      • migrations: 数据修改表结构
        • 内部有django自动创建的数据库修改表结构的操作记录,注意,仅记录了对表结构的修改,数据库中的记录的操作,不记录。
      • __init__      把文件夹转成包
      • admin    django为我们提供的后台管理
        • 包括了登录、添加、删除、权限管理等基本功能。
      • apps    配置当前app
      • models:  ORM,写入指定的类,通过命令创建和修改数据库结构
      • tests:     单元测试
      • views:    和cmdb相关的所有业务,业务逻辑代码
    • 不同文件、模块间的调用过程中,注意核实settings中环境的配置
    • 配置模板的路径
      • 在settings中,DIRS:[os.path.join(BASE_DIR,"模板包名字")] 一般的是templates
    • 配置静态文件的路径
      • 在settings中,STATIC_DIR后面,加上STATICFILES_DIRS = (os.path.join(BASE_DIR,"静态文件名字"),)  一般地静态文件名为static
  •  django项目创建步骤
    • 1 创建django工程     django-admin startproject 工程项目名
    • 2 创建app   cd工程文件夹  python manage.py startapp  app名
    • 3 静态文件配置
      • 静态网页,静态网页是相对于动态网页而言,是指没有后台数据库、不含程序和不可交互的网页。
        • 静态网页优势:可以公开(即副本可以证明给任何人)。托管没得任何特殊的要求。(不需要特殊的中间软件比如超文本预处理器、公共网关接口)没得网络服务器或应用服务器,比如直接从CD-ROM(激光唱片-只读存储器)或USB闪存驱动器读取内容,可以通过网络浏览器直接访问。网站更安全,HTML页面不会受Asp相关漏洞的影响;而且可以减少攻击,防SQL注入。数据库出错时,不影响网站正常访问。不需要编译,所以速度快,节省服务器资源。网址格式友好,搜索引擎容易识别。内容是固定的,交互性差,内容更新维护复杂。没有自动化的工具,维护大量的静态页面文件是不现实的。无法充分支持用户/客户的需求(外观选择,浏览器的支持,Cookie)。
      • 静态文件,一般是指css,js,img等类似的,让html直接引用的,可以直接暴露给用户的文件即归为静态文件.
      • 静态文件配置方式:
        • 方式一:
          • 在settings文件下,配置文件中已经有了静态文件的别名,STATIC_URL='/static/'   在这之后添加  STATICFILES_DIRS=[os.path.join(BASE_DIR,'    ')]   .使用的时候,用别名static.
    • 4 模板配置
    • 5 csrf
    • 6 定义路由规则    urls.py       请求字段——》响应函数名(视图函数、)
      • urlpatterns=[ ]  
    • 7 定义视图函数   app 下 views   判断数据发送方式,通过request拿数据,数据处理,数据返回
      •   HttpResponse-传字符串、               HttpResposnse(" 字符串 ")
      •   render-传HTML模板路径、               render(request ,"abc.html",{ 替换形式字典 })
      •   redirect-传       /URL)                       redirect(' /abc/ddd ')

django请求基本周期

  • 基本周期
    • 请求                             一般情况下,GET方式用来获取数据,POST用于提交数据。其他的提交方式还有PUT/DELET等
    • 路由关系映射
    • 视图函数
    • 数据       html模板
    • 渲染以后返回给用户
  • 完整周期:

  

路由系统(urls)

  • 常见的url匹配规则:
    • 1  一 一对应静态匹配,url('index/',views.index)           url('home/',views.Home.as_view())   在设置路由关系时字段内容最后要加上$终止符,否则在匹配过程中,会由于不是截止的精确匹配,因而前后优先级导致匹配错乱。     例如,url('index/$',views.index)
    • 2 利用正则实现动态匹配(类似传递位置参数)   url(r'detail-(\d+).html',views.detail)
      • 正则当中使用分组的情况下,会有二次匹配的情况,传递的参数会将所有的结果都传到视图函数中.
    • 3   利用正则表达式的分组实现(在函数调用时,参数以关键字形式传递)               url(r“detail-(?p<nid>\d+)-(?p<uid>\d+).html”,views.detail)此url路由匹配规则在传递获取的参数时,会以nid=***,uid=***进行传递     为了方便,在views定义视图函数的时候,直接用不定长参数*args,**kwargs定义。
    • 注意
      • 要想从路径中捕获某些信息,只需要在对应的正则内容上面加分组,进行二次匹配
      • 使用正则的时候,前面开始的反斜杠不用加,会自动添加
      • 正则表达式前面的r虽然是可选项,但一般情况下最好是加上.
      • 由于路由系统的匹配顺序是自上而下的顺序匹配,所以,在正常的匹配规则最后,最好是加上 ‘$’ 终止符,做精准匹配,防止出现上面的url匹配规则把某类的匹配全部截获,下面的匹配规则得不到有效执行。
    • 获取当前url信息,request.path_info
    • 路由分发,主要的目的是实现不同app之间进行解耦.当请求到顶级(项目同名)url的时候,通过include,根据请求的关键字,对请求进行一个分发,同时在不同的app中建立局部的urls文件,避免不同app之间urls放在一起,增强系统的易读易维护性。              顶级url负责分发,  例如, url("monitor/",include("app003.urls")),url("cmdb/",include("app06.urls"))
      • 首先 from urls import include
      • 前面的匹配规则可以用正则,也可以为空,当为空的时候,会直接到各个app中进行进一步匹配.
    • 路由的反向解析
      • 目的是不在代码中把url写死,而是通过反向查询动态获取。 
      • 主要应用方式:
        • 在模板中,利用{%url     '路由中给匹配规则起得别名' %}
        • 在视图函数中,reverse的应用,利用reverse函数,可以根据路由名称(别名),返回具体的路径。注意当路由中有正则表达式时,需要把代替填充的内容一并传递过去。
    • url默认值,在路由系统中,可以给视图函数传递默认值,此时,需要保证视图函数有对应的形参用于接收默认值。     例如     url("index/",views.index,{"name":"root"}) ,这时候,index视图函数的name参数会接收路由调用时自动传递过来的默认值root。 
    • url命名空间。使用反向解析的时候,在路由分发的情况中,如果出现不同的url指向相同函数并且url所定义的别名相同等情况(例如不同app定义的url匹配规则,虽然在不同的app中,但定义别名一致时命名相同),单纯使用url的name没有办法得到确切的url路径,这时需要同时利用url的name,和定义路由时所一并定义命名空间。 定义命名空间的基本语法     url(“a/”,include("app01.urls",namespace="a1")) url(“b/”,include("app01.urls",namespace="b1"))    通过reverse( ‘ 命名空间namespace:路由name ’ )   可以确定url路径
    • url,  re_path,  path
      • re_path实际上就是之前的版本中的url方法,一般是结合正则表达式使用
      • 一般情况下,使用url、repath进行匹配后,如果规则中有正则并且分组的话,匹配出来的分组内容实际上是以字符串形式,传递给视图函数的。另外,如果正则表达式中出现有名分组,需要对捕获到的内容进行类型强转。上述情况在django2.0以上的版本适合用path方法
      • path方法,与转化器
        • path方法配合上内置的转化器,可以方便的将前端的数字等类型,传到后端。
        • 转化器基本使用语法       path(' 包含转换器的url规则 ',视图函数,别名)           注意转换器是用尖括号包裹的<匹配转换器类型:分组名称>,同样的,url规则不需要前导斜杠。 
        • 当前内置的转换器,有int,str,uuid, slug,  path
        • 自定义转化器
          1. 定义转换器类
            • regex 类属性,字符串类型
            • to_python(self, value) 方法,value是由类属性 regex 所匹配到的字符串,返回具体的Python变量值,以供Django传递到对应的视图函数中。
            • to_url(self, value) 方法,和 to_python 相反,value是一个具体的Python变量值,返回其字符串,通常用于url反向引用。
            • 1 # 新建py文件
              2 class FourDigitYearConverter:  
              3     regex = '[0-9]{4}'  
              4     def to_python(self, value):  
              5         return int(value)  
              6     def to_url(self, value):  
              7         return '%04d' % value
              View Code
          2. 进行url配置注册
            • 使用register_converter 将其注册到URL配置中
            • 1 from django.urls import register_converter, path  
              2 from . import converters, views  
              3 register_converter(converters.FourDigitYearConverter, 'yyyy')  
              4 urlpatterns = [  
              5     path('articles/2003/', views.special_case_2003),  
              6     path('articles/<yyyy:year>/', views.year_archive),  
              7     ...  
              8 ]
              View Code

 

视图函数 

    • 本质上就是一个python函数,但必须有返回值,也就是必须有return,返回内容是按规定的格式。一般是存放在views.py文件中。
    • 视图函数操作的对象,可以简单的分为请求对象、响应对象两部分,其中request就是请求对象,封装了前端发过来的请求信息。响应对象有HTTPResponse、render方法本质上是对响应内容的封装并以HTTPresponse对象形式返回、
    • 后台数据获取
      • request是前端数据的打包
      • 常用的request的属性
        • request.path_info     获取当前url中的【路径信息】
        • request.method 拿到当前请求的请求方式,常见的有POST,GET,PULL,PUT等。常用于视图函数判断请求方式
        • request.body     用户发起请求报文的请求体,通过请求体的原始数据,能够解析出请求体中的所有信息。例如,前段发起的ajax请求,如果发送的json数据,此时,contentType不是urlencoded,request.POST等是解析不出来的   
        • request.GET,首先通过消息头中的contentType==‘urlencoded’,然后解析出路径中的参数信息
        • request.POST,首先通过消息头中的contentType==‘urlencoded’,解析出请求体中携带的参数信息,存储post请求信息       
        • request.FILES ,解析并存储文件信息
        •  一般情况下,GET方式用来获取数据,POST用于提交数据。其他的提交方式还有PUT/DELET等 
      • 常用的request的方法
        • request.Meta()
        • request.get_full_path() 获得当前url中的 【路径信息】和【请求参数信息】
        • request.POST.get() 获取指定的参数信息
        • request.GET.get()  获取指定的url参数信息
        • request.POST.getlist() 当提交的数据包含复选框等并列内容时,用getlist可以统一接收。
        • request.FILES.get() 
          • 要上传文件,需要在form标签中,需要做设置,enctype='multipart/form-data'
          • 上传文件时,FILES.get()获取上传的文件对象的属性信息。
        • request.FILES.size()
        • request.FILES.chunks()
          • 分段获取的,上传的文件内容。需要读取文件内容的话,需要对FILES.chunks()进行循环。
      • request中封装了url请求的所有原生信息,实际上是以类的形式存在的
        • 要查看请求体的详细信息,需要导入WSGIRequest    ,  from django.core.handlers.wsgi import WSGIRequest
        • request.environ 可以拿到请求体的完整信息,字典形式存放的
        • request.environ[ ] 可以拿到指定的信息内容,   例如,request.environ['HTTP_USER_AGENT'] 
      • reverse函数,可以根据路由的名称,反向解析出完整的路由信息。
        • 导入,from django.urls import reverse
        • 对于未指明namespace的,    reverse(路由name);                对于指明namespace的,                   reverse(命名空间namespace:路由name)
      • 返回内容
        • 包含django的模板标签的html文件,并非真正的html文件(浏览器是不能对这种文件直接进行解析的),render方法是在传输响应信息前对模板文件进行了数据渲染,替换掉了模板标签。
        • return HttpResponse()  返回简单字符串                           return render(request,"    html文件",{  替换内容  })返回取到数据渲染后的html文件内容        return redirect( ' 重定向 url  ' )     
        • 数据返回的时候,cookie的设置内容是通过响应头传递回去的
      • FBV(function base views)   与  CBV(class base views)
        • FBV 由url直接对应(映射)函数名,  CBV 由url直接对应(映射)到指定的类。
        • CBV 本质上,通过dispatch反射,实现根据数据请求的发送方式选择不同方法执行。执行对应请求的方法前会优先执行 dispatch 方法(在get/post/put...方法前执行),dispatch() 方法会根据请求的不同调用相应的方法来处理。其实,Django 的 url 是将一个请求分配给可调用的函数的,而不是一个类,要实现基于类的视图, 主要还是通过父类 View 提供的一个静态方法 as_view() ,as_view 方法是基于类的外部接口, 他返回一个视图函数,调用后请求会传递给 dispatch 方法,dispatch 方法再根据不同请求来处理不同的方法。
        • CBV方式,可以通过重写dispatch,实现自定制功能。
        • FBV代码示例
          • urlpatterns = [
                path("login/", views.login),
            ]
            urls.py
            from django.shortcuts import render,HttpResponse
            
            def login(request):
                if request.method == "GET":
                    return HttpResponse("GET 方法")
                if request.method == "POST":
                    user = request.POST.get("user")
                    pwd = request.POST.get("pwd")
                    if user == "runoob" and pwd == "123456":
                        return HttpResponse("POST 方法")
                    else:
                        return HttpResponse("POST 方法1")
            View Code
        • CBV代码示例

          • urlpatterns = [
                path("login/", views.Login.as_view()),
            ]
            urls.py
            from django.shortcuts import render,HttpResponse
            from django.views import View
            
            class Login(View):
                def get(self,request):
                    return HttpResponse("GET 方法")
            
                def post(self,request):
                    user = request.POST.get("user")
                    pwd = request.POST.get("pwd")
                    if user == "runoob" and pwd == "123456":
                        return HttpResponse("POST 方法")
                    else:
                        return HttpResponse("POST 方法 1")
            views.py

             

      • 装饰器(定义方式是一样的,调用方式不一致)
        • 基于FBV的
        •  1 #---------基于FBV的装饰器实现COOKIE登录验证-----------
           2 
           3 def auth(func):
           4     def inner(request,*args,**kwargs):
           5         v = request.COOKIES.get("user111")
           6         if not v:
           7             return redirect('/login/')
           8         return func(request,*args,**kwargs)
           9     return inner
          10 
          11 @auth
          12 def func01(request):
          13     return HttpResponse("hello world")
          View Code
        • 基于CBV的
          • 基于CBV的视图函数,加装饰器时,需要导入模块  from django.utils.decorators import method_decorator      然后通过@method_decorator(auth)加装饰器
          • 具体调用方式:
            • 方式一,可以直接对类函数进行装饰
            •  方式二:对类里的方法全都装饰的情况下,可以利用dispatch函数。重写dispath函数,并加上装饰器,用super(类,self).dispatch(request,*args,**kwargs)进行正常的方法执行,在此执行的前后,可以自定义部分功能,实现装饰器的功能。
            • 方式三:直接在类名上面加装饰器,本质上,方式三是对方式二的简化
            •  1 #---------基于CBV的装饰器实现COOKIE登录验证-----------
               2 
               3 def auth(func):
               4     def inner(request,*args,**kwargs):
               5         v = request.COOKIES.get("user111")
               6         if not v:
               7             return redirect('/login/')
               8         return func(request,*args,**kwargs)
               9     return inner
              10 
              11 @method_decorator(auth,name="dispatch")                   #方式三
              12 class Order(views.View):
              13 
              14     @method_decorator(auth)                            #方式二
              15     def dispatch(self,request,*args,**kwargs):
              16         return super(Order,self).dispatch(request,*args,**kwargs)
              17 
              18     @method_decorator(auth)                             #方式一
              19     def func1(self,request):
              20         return HttpResponse("hello world普通函数")
              View Code

Templates 模板

  • django默认的搜索模板的顺序是,先到project目录的Templates中搜索,如果没有,则根据settings中app的注册顺序,依次搜索。所有的静态文件的搜索都是按这个顺序执行。
  • 模板基础语法只有   {{   }}  和 {%     %} 两种。前者是用于传递渲染变量用的,后者是用于渲染标签的。
  • 可以直接定义html,然后实现在视图函数中进行调用
  • 变量的渲染与使用
    • 变量的渲染是通过  {{   }} 实现的。
    • 使用方式:
      • 模板中用 {{ }} 定义好变量的位置
      • 在视图函数中,使用render方法进行变量传递,如果是传递单个变量,可以直接以字典形式在render方法中用第三个参数传递过去,如果是变量比较多,即可以一个个的传递,也可以通过locals()方法,把视图函数中的变量打包成指定格式传递到模板中。
    • 深度查询
      • 在传递的变量是列表、字典、对象等类型的数据时,直接在模板中用 “ 。 ” 对需要的内容进行深度查询,从而拿到相应的内容。
  • 过滤器,即函数的使用
    • {{ 变量 | 内置函数:参数 }}
    • 常用的内置函数(内置过滤器)
      • data      定制时间显示格式,{{mydata | data:'Y-m'}} 日期显示格式为年-月
      • default     定制默认显示内容,当没有接收到变量的时候,如果没有默认内容,变量的位置直接为空
      • filesizeformat   格式化输出文件大小 {{ myfile | filesizeformat }} 将文件的大小直接按标准格式显示出来
      • slice 切片
      • truncatechars    按字节进行内容截断
      • truncatewords    按单词截断
      • safe 安全解析标志,在正常情况下,如果是传递包括<>的内容时,django会先通过html特殊符号对照表,对内容进行编译再传递,目的是防止不安全代码注入。
        • 通过safe过滤器,把传递的内容标注为安全的,django会把这部分内容正常写入html文件,交给客户端浏览器解析,显示成正常标签内容。
      • add,
      • upper  
  • 标签的渲染和使用
    • {%  %} 渲染控制语句,基本的逻辑控制语法如下:
      • for循环基本语法:
        • {%for   条件  %}   循环体        {% endfor %} 
        • {%for   条件  %}   循环体    {%empty%}当遍历到的内容为空时的执行语句    {% endfor %} 
        • {{forloop}}可以拿到当前循环的次数,即循环的序列号。使用时直接 forloop.count,另外还有forloop.count0从0开始计数,forloop.revcounter ,forloop.revcounter0 ,forloop.last是否最后一个,forloop.first是否第一次循环。  当出现嵌套循环的时候, forloop.parentloop将每次循环过程中,父循环的上述6个参数打包。
      • 条件语句基本语法
        • {%if     条件%}      满足条件情况下执行的函数体或显示的标签内容       {%else   条件 %}   不满足条件时,执行或显示的内容 
        • with as  当正常的变量名或深度查询等特别长不方便使用的时候,创建简写
        • {%with 正常的变量或深度查询等  as  简写内容%}  逻辑语句  {%endwith%}
      • {%csrf_token%}标签
        • 在form表单中,加入{%csrf_token%},这样在渲染的时候,django会在页面中,加上一个csrf_token标签,用于进行中间件检测。
  • 自定义函数(过滤器)或标签
    • a. app下创建templatetags目录
    • b. 创建py文件
    • c. 自定义标签,导入模块 from django import template    from django.utils.safestring import mark_safe  创建template对象,得到register  实例化自template.Library。名字必须是register不能用其他的。
    • d. 自定义过滤器,加装饰器@register.filter,如果是自定义标签,此时加装饰器  @register.simple_tag,
    • e. settings中注册当前app
    • f. 在引用文件顶部导入函数文件  { % load 函数所在的py文件名 % },
    • g. 执行自定义过滤器或标签
      • 执行标签  { % 自定义标签名 参数1   参数2  …… % }   
      • 调用自定义函数(过滤器)的时候格式类似调用python内置函数,{{参数|函数名:其他参数}}  当传的参数较多时,用字符串,  {{参数 | 函数名:“参数二,参数三,”}}。这种方式的缺点是,参数数量有限制,函数名后最多放两个参数,并且元素之间不能有空格。优点是结合{%if  变量| 自定义函数:参数  执行条件%} 实现if判断条件,放在 template  模板流程控制中。如果参数再多的情况,则直接使用自定义标签完成。
      
  • 继承、组件。
    • 继承,在布局重复的情况下,可以使用html母版,通过继承母版的设置,提高程序的可读性、易维护性,降低维护成本
      • 使用方式:
        • 1 定义布局母版html ,在母版中用{%block 模块名字%}{%endblock%}定义可以替换的模块及其位置。
        • 2 在引用html文件中,声明引用的母版      {%extends “布局母版html文件名字”% }
        • 3 定义好当前html文件用于替换布局母版的内容。 {%block 模块名字%}自定义的内容{%endblock%}
        • 4 在具体页面中还有特有的css,js的情况,在母版中留出自定制css,js的位置,一般可以在模板的style位置后加入css的block,在js包括jquery位置加js的block,在具体页面中用自定义替换即可
      • 使用继承的注意事项:
        • extends标签必须在引用文件的首行
        • 在带引用的母版文件中,{%block 模块名字%}{%endblock%}越多越好,可以理解为越多情况下的可改造程度越高。
        • 一般情况下,子版中写入内容后,会直接把母版中的{%block 模块名字%}默认内容{%endblock%},其中的默认内容直接用子版定义的内容替换掉。如果想在母版内容保留的前提下,添加内容,可以在定义子版内容的时候,加一个{{ block.super }} 的标签。
        • 一个html页面,只能继承一个母版。可以理解为电脑的主板,页面的整体框架,可以从母版中继承过来。
    • 组件,对于页面中的重复布局,可以使用组件,提高程序的可读性、易维护性,降低维护成本
      • 1 定义组件html文件
      • 2 在具体html文件中,用include对组件进行引用       基本语法,{%include ' 引用组件的html文件名称 '%}
      • 组件可以理解可插拔设备。
    • 对于继承的母版、页面引用的组件,django会在进行渲染之前,先把这些内容都拿过来,生成一个完成的模板文件,然后再融入数据库替换的数据,最后在进行渲染。  
    • 当模板html文件中,既有extend继承,又有load时,必须将load放在extend之后,主要原因是extend继承过来的是模板文件的整体框架。

 

模型层Models

Models,数据库操作(ORM) 

  • 主流ORM可以分成 db first (需要先自己登陆数据库建立表结构,此后经过执行会自动创建相应的类,对表结构进行操作的时候,可以直接对这些类进行操作来完成),code first(先写代码,创建需要的各种类,然后通过执行语句,利用创建的类创建数据库表)两类。主流的orm是code first类型。
  • 当前django提供的ORM,只能完成对数据库中的表进行操作,数据库层面上的操作,还需要在数据库层面上进行布局。 
  • 另外需要注意的是,py3.x 的解释器进行数据库操作的时候,django默认的数据库驱动接口是mysqldb,而py3.x 用的数据库驱动接口是pymysql,所以需要使用前对驱动接口进行设置,在项目名文件目录下的init文件中,写入如下内容:
    • import pymysql
      pymysql.install_as_MySQLdb()
  • 创建数据表类
    • 根据类创建数据表

      • 在app下,models.py中,创建类,继承models.Model。注意,models.py命名不能改,否则会报错
      • 通过类创建表
      • 在类中,通过models的方法,定义字段,其中可选属性null=True,定义可以为空。例如     username=models.CharField(max_length=32)
      • 创建字段的方法,分为三大类,字符串、数字、时间、二进制,常用的有:CharField定义一般的字符串  IntegerField定义数字    DateField定义日期     DateTimeField定义时间    EmailField 定义邮箱格式     GenericIPAddressField定义IP类型        URLField定义URL          AutoField定义自增列,必须加属性primary_key=True   
      • 需要注意的是,EmailField、URLField、GenericlPAddressField等类型,基本上是在使用django提供的admin时才能用得上,一般情况下,就用CharField定义一般的字符串  IntegerField定义数字    DateField定义日期  AutoField定义自增列,必须加属性primary_key=True   
      • 字段的常用参数有:   null——》是否为空,default——》默认值,primary_key——》主键,db_column列名,db_index——》索引,uique——》唯一索引,unique_for_date,unique_for_mounth,unique_for_year,auto_now——》创建时,自动获取时间,auto_now_add——》更新时,自动获取当前时间,需要注意的是,使用update对数据进行更新的时候,这种操作的时间不会记录更新,只有用 ‘=’ 重新赋值,然后save的操作才会记录更新时间。choices——》元组形式定义分组,把内容放在内存中,运行的时候admin中显示的下拉框,实现了连表查询的显示效果,并且避免了连表查询的低效率。      blank——》在admin中,定义是否为空      verbose_name——》在admin中设置是否为中文        editable——》设置admin中是否可编辑      error_messages——》错误提示        help_text——》在admin中提示信息   validators——》自定义错误信息      protocol用于GenericIPAddressField设置ip协议类型
        • settings中,INSTALLED_APPS中,注册app
        • 通过manage创建表结构,    python manage.py makemigrations            注意,在创建之前,需要把在settings中,把当前app名加入INSTALLED_APPS
        • 用django默认的数据库是sqlite,如果用mysql,需要,1 在settings中,把数据库引擎设置修改,
          #DATABASES = {
          # 'default': {
          # 'ENGINE': 'django.db.backends.mysql',
          # 'NAME': 'dbname',
          # 'USER':'root',
          # 'PASSWORD':'mysql',
          # 'HOST':'',
          # 'PORT':'',
          # }
          # }
        • 另外,需要注意的是,利用django使用mysql时引擎默认是用的mysqldb,但是,当前python3.x中,还没有mysqldb。需要在和【项目同名】的文件夹下,__init__文件中,设置
          #import pymysql
          # pymysql.install_as_MySQLdb()
        • 当使用py3.x解释器,跑django2.0版本的时候,会报错,django.core.exceptions.ImproperlyConfigured,即版本错误。这时,需要在解释器程序中Python\Python36-32\Lib\site-packages\Django-2.0-py3.6.egg\django\db\backends\mysql 这个目录下对下面的内容注释掉
          • if version < (1, 3, 3):
                 raise ImproperlyConfigured("mysqlclient 1.3.3 or newer is required; you have %s" % Database.__version__)
        • 执行migrate命令,在数据库中创建表,类似于数据库的确认操作, python manage.py migrage
        • 如果要查看orm执行的sql语句,可以进行settigns中设置后打印,
          •  1 LOGGING = {
             2     'version': 1,
             3     'disable_existing_loggers': False,
             4     'handlers': {
             5         'console':{
             6             'level':'DEBUG',
             7             'class':'logging.StreamHandler',
             8         },
             9     },
            10     'loggers': {
            11         'django.db.backends': {
            12             'handlers': ['console'],
            13             'propagate': True,
            14             'level':'DEBUG',
            15         },
            16     }
            17 }
            View Code
        • 对数据库的表单结构修改(字段内容)后,即对定义表的类进行修改以后,用manage.py 执行makemigrations,migrate命令进行确认操作。
  • 数据库单表操作与多表操作(外键),增删改查
    • 单表操作
      • 根据类对数据库表中的数据进行各种操作,注意:增加、更新、查询传递参数时,都可以通过 ** 传递字典进行操作
      • 增加:    
        • 方式一,直接创建  models . 表名 .objects.create(字段1:数值,字段2……)    当字段较多,可以先建一个存储信息的字典,然后把字典穿进去,当传递字典时,需要在字典名前加 **           models . 表名 .objects.create(**字典名)        执行的时候是有返回值的,返回的是创建的记录对象。
        • 方式二,通过创建一个对象信息,然后把保存对象              obj=models . 表名(字段1:数值,字段2……)               obj.save()        执行的时候是有返回值的,返回的是创建的记录对象。
        • 当定义字段时,使用models.EmailField()    models.GenericIPAddressField()等特殊格式时,如果用    create创建,或者用update更新,都不会有格式验证。只有在执行django admin时会有格式验证。
      • 查询:
        •  models.表名.objects 拿到的是一个可以对表进行操作的句柄。
        • all()拿到的是对象形式存储信息的QuerySet(形式上类似于列表)     models.数据表名.objects.all()
          • 对于查询的结果,可以通过 .order_by()进行排序                     models.数据表名.objects.all().order_by()       models.UserInfo.objects.filter(id__gt=1).order_by()
          • .first() 结果中的第一个           .count()对结果进行计数          .last() 结果中的最后一个
        • 利用filter添加where查询条件,结果也是以QuerySet存储        models.数据表名.objects.filter(筛选条件),可以通过“__”实现逻辑模糊查询。gt->greater than,gte->greater than or equal,lt->less than ,lte->less than or equal
          •  models.UserInfo.objects.filter(id=1)  # 拿到id=1的对象,结果是queryset
          •  models.UserInfo.objects.filter(id__gt=1) # 拿到id大于1的对象,结果是queryset
          •  models.UserInfo.objects.filter(id__lt=1) # 拿到id小于1的对象,结果是queryset
          • models.UserInfo.objects.filter(id__gte=1) # 拿到id大于等于1的对象,结果是queryset
          •  models.UserInfo.objects.filter(id__lte=1) # 拿到id小于等于1的对象,结果是queryset
          •  models.UserInfo.objects.filter(name__contains='H') # 拿到name字段中包含大写H的对象,结果是queryset
          •  models.UserInfo.objects.filter(name__icontains='H') # 拿到name字段中包含大写H及小写h的对象,结果是queryset
          • 筛选条件中,多条件并列时,可以直接用“,”对多条件进行连接。
        • 另外,用models.数据表名.objects.get(筛选条件) 能取到单条数据,取不到内容或者是取到的结果是有多条时,报错!需要try一下。需要注意的是,大部分的查询结果是queryset存储的结果,但get方法是获取的单个的对象。
        • models.数据表名.objects.exclude(筛选条件)  可以实现反向查询,即选出不满足筛选条件的记录,并把结果存入queryset中存储。
        • 一般情况下,查询的结果,不论是all()或者是通过fiter()取到的都是queryset形式储存的对象的序列,再链一个values() 拿到的是queryset形式存储的字典的序列可以指定取出的字段   例如models.UserInfo.objects.filter(id__gt=1).values(‘id’,'name'),  如果链一个values_list() 拿到的则是queryset形式存储的元组的序列,可以通过索引值,拿到指定的字段
        • queryset可以调用的其他常用方法
          • order_by()方法,对queryset结果,按指定规则进行排序,返回值仍然是queryset。排序规则支持多条件,可以直接用“,”对条件进行连接。
          • reverse() 方法,也是queryset进行反向操作时进行调用,返回值仍然是queryset。
          • values(指定键值)方法,可以从queryset的对象列表中,拿到每个对象的指定键值对即字典形式,返回结果以queryset形式存储的字典键值对。
          • values_list(指定键值) ,功能类似于values,但不同的是,返回的结果是queryset形式存储的元祖,不含键只有值。在取值的时候,用索引值。
          • distinct()  ,主要功能是进行去重。
          • first( )当queryset中有对象时,取到的是第一个对象,没有对象时,取到的是none。用起来比get方法更方便。
      • 删除:
        • 方式一,可以在queryset直接调用delete方法
          • models.数据表名.objects.filter(筛选条件).delete()
        • 方式二,可以在queryset中利用first,last等取到【记录对象】后,直接调用delete
          • models.数据表名.objects.filter(筛选条件).first().delete()
      • 修改(更新):
        • 只能由queryset进行方法调用
        • models.数据表名.objects.filter(筛选条件).update(字段=修改的数值)  
    • 多表(外键)
      • 定义数据表结构的类中,定义外键对应关系。       外键关系名 = models.ForeignKey(to=关联表名,to_field=关联字段,default=指定默认值, on_delete=models.CASCADE)                                 外键关系名_id    ——》外键字段(自动)                            on_delete=models.CASCSDE 是在django2.x以后版本加入的,最明显的一个作用,是避免两个表之间的数据不一致。models.CASCADE是默认情况下的取值,另外的取值分别为:
          • CASCADE:此值设置,是级联删除。
            PROTECT:此值设置,是会报完整性错误。
            SET_NULL:此值设置,会把外键设置为null,前提是允许为null。
            SET_DEFAULT:此值设置,会把设置为外键的默认值。
            SET():此值设置,会调用外面的值,可以是一个函数。
      • 调用执行过程中,外键关系名指向关联表的对象
      • 当用all(),filter()等方法直接拿到结果的时候,跨表拿内容,直接用  queryset存储的表对象 外键关系名 字段名 ” 来获取                                      例如item.group_foreignkey.name。此时的外键关系可理解为封装在queryset对象中的子级对象,指向关联表。
      • 当用values(),或者values_list() 拿到结果的时候,跨表拿内容,不能用 “ . ”   需要改成双下划綫“ __ ”    例如:item.group_foreignkey__name。并且,在用values,或者values_list() 须在视图函数中完成
      • 一对一关系,实际上是对一张字节比较多的表,进行的拆分。建立方式可以是通过唯一的外键
      • 一对多关系,通过建立外键,可以实现表之间的一对多的关系创建
        • 用建立外键关系后,通过  ‘ .外键关系_id ’ 可以获取从属表中,保存的外键值,利用 ‘ . 外键关系 ’ 则可以直接取得对应的对象,直接用连接符 ‘ . ’ 可进一步通过跨表查询获取具体的属性。
        • 一对多关系常见的查询方式:
          • 如果通过 ‘ . ’ 跨表查询获得的是外键链接的对象,当这个对象中仍然包含其他的外键关系时,可以依次用  ‘ . ’ 跨表查询获得
          • 双下划綫,实现跨表查询,当跨表查询的结果作为参数使用时,利用 __。例如在,value()中传递参数的时候。
      • 多对多关系建立
        • 方式一,通过手动建立第三张表作为关系表,分别通过外键和另外的两张表建立外键关联,最终实现两张关联表之间的多对多
        • 方式二,利用r=models.ManyToManyField() ,在创建原始的关联表的时候,由django自动创建多对多的第三张关系表。r作为操作句柄可以实现对第三张关系表的操作。
          • 利用r操作对应关系的时候,先获取一张关联表(创建r的表)中的对象,  例如,  obj=models.关联表名.get(id=1)
          • 然后通过r对关联关系进行操作。      obj.r.add(2)   obj.r.add(1,2,3)   obj.r.add(*[3,4,5,6])     obj.r.remove(2,3)   obj.r.clear()     obj.r.set([1,2,3]) 用set设定更新关系时,传列表不用加*  。      obj.r.all() 拿到的是一个另一张表的对象, obj.r.filter()  
          • 方式二默认的只可以创建两张表之间的关系。如果需要多张表之间建立关系,需要用方式一。
    • 反向查询

 

posted @ 2019-06-02 11:26  林山风火  阅读(15)  评论(0)    收藏  举报