• Django


    Django

    安装

    • 安装:pip install django,默认安装在python 的 Scripts 目录下
    • 将Script添加至环境变量:如C:DprogramPython354Scripts
    • CMD中运行,创建Django工程:django-admin.exe startproject mysite(或者 django-admin startproject mysite) 创建工程mysite目录;mysite可以换成其他目录名
    • 在CMD中运行manage.py,启动Django功能:python manage.py runserver 127.0.0.1:8001

    运行

    • 专业版pycharm:可以直接创建django项目,然后可以选择django项目运行
    • 非专业版pycharm:不能直接创建django项目,在run图标左侧,选择manage点击可看见Edit Configurations,点击后可看见Parameters,只需配置“runserver 127.0.0.1:8001”,然后保存即可运行manage.

     

    project目录

      mysite
        - mysite        # 对整个程序进行配置
            - init
            - settings  # 配置文件
            - url       # URL对应关系
            - wsgi      # 遵循WSIG规范,uwsgi + nginx
        - manage.py     # 管理Django程序:
    

    manage命令

    manage.py runserver 0.0.0.0
    python manage.py startapp appname
    python manage.py syncdb
    python manage.py makemigrations
    python manage.py migrate
    python manage.py createsuperuser
    

    APP 目录

    创建app:python manage.py startapp app_name

    migrations:     数据库操作记录,只记录修改表结构记录,不包括插入等
    admin:          django提供的后台管理
    apps:           配置当前app
    models:        ORM,写指定的类,通过命令可以创建数据结构
    tests:          单元测试
    views:          业务代码  
    

    配置

    创建完project,做如下配置

    1、配置模板的路径

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

    2、配置静态目录,在setting文件最下面

       
    STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),)
    
    <!-- 引用静态文件-->
    <img class="logo left" src='/static/in.png' alt="Logo">
       
    

    3、数据库

       
    DATABASES = {
        'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME':'dbname',
        'USER': 'root',
        'PASSWORD': 'xxx',
        'HOST': '',
        'PORT': '',
        }
    }
    
    # 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替
    
    # 如下设置放置的与project同名的配置的 __init__.py文件中
    import pymysql
    pymysql.install_as_MySQLdb()
       
    

    MTV模式

      
    Model:数据库,负责业务对象与数据库的对象(ORM)
    Template: 模板文件,负责如何把页面展示给用户
    View: 业务处理,负责业务逻辑,并在适当的时候调用Model和Template
    urls分发器:将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template
      
    

    实例

     1 from django.shortcuts import render
     2 from django.shortcuts import HttpResponse
     3 from django.shortcuts import render
     4 from django.shortcuts import redirect
     5 # Create your views here.
     6 
     7 user_list = [
     8     {'username':'a','email':'aaaaaa','gender':'M'},
     9     {'username':'b','email':'bbbbbb','gender':'M'},
    10     {'username':'c','email':'cccccc','gender':'F'}
    11 ]
    12 
    13 
    14 def home(request):
    15     if request.method == "POST":
    16         u = request.POST.get('username')
    17         e = request.POST.get('email')
    18         g = request.POST.get('gender')
    19         temp = {"username":u,"email":e,"gender":g}
    20         user_list.append(temp)
    21     return render(request,'home.html',{'user_list':user_list})
    22 
    23 def login(request):
    24     # 'django.middleware.csrf.CsrfViewMiddleware' 在setting中需要注释掉这一项,否则提交表单时会出错
    25     #第一种打开html文件方式
    26     # f = open('templates/login.html','r',encoding='utf-8')
    27     # data = f.read()
    28     # f.close()
    29     # return HttpResponse(data)
    30 
    31     # 第2种打开html文件方式: 注意在setting需要配置template路径DIRS,
    32     # TEMPLATES = [
    33     #     {
    34     #         'BACKEND': 'django.template.backends.django.DjangoTemplates',
    35     #         'DIRS': [os.path.join(BASE_DIR, 'templates')],
    36     #     },
    37     # ]
    38     error_msg = ''
    39     if request.method=="POST":
    40         user = request.POST.get('user',None)
    41         pwd = request.POST.get("password",None)
    42         if user=='root' and pwd == '123':
    43             #  跳转到百度
    44             # return redirect('www.baidu.com')
    45             return redirect('/home')
    46         else:
    47             # 用户密码不匹配
    48             error_msg = 'user or password error'
    49 
    50 
    51     return render(request, 'login.html',{'error_msg':error_msg})
    views
     1 from django.contrib import admin
     2 from django.urls import path
     3 from django.shortcuts import HttpResponse
     4 
     5 from cmdb import views
     6 
     7 
     8 
     9 
    10 urlpatterns = [
    11     path('admin/', admin.site.urls),
    12     path('login', views.login),
    13     path('home', views.home),
    14 ]
    url
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="/static/comments.css"/>
        <title>Title</title>
    
        <style>
            label{
                    width:80px;
                    text-align:right;
                    display:inline-block;
            }
    
    
        </style>
    </head>
    <body>
        <form action="/login" method="post">
            <p>
                <label for="username">用户名:</label>
                <input id="username" type="text" name="user" />
            </p>
            <p>
                <label for="password">密  码:</label>
                <input id="password" type="text" name="password" />
                <input type="submit" value="提交"/>
                <span style="color: red;">{{error_msg}}</span>
            </p>
        </form>
        <script src="/static/jquery-1.12.4.js"></script>
    </body>
    </html>
    login.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div>
        <form action="/home" method="post">
            <input type="text" name="username" />
            <input type="text" name="email" />
            <input type="text" name="gender" />
            <input type="submit" value="添加" />
        </form>
    </div>
    
    
    <div>
    
        <table>
            {% for row in user_list %}
                <tr>
                    <td>{{row.username}}</td>
                    <td>{{row.gender}}</td>
                    <td>{{row.email}}</td>
                </tr>
            {% endfor %}
        </table>
    
    
    
    
    </div>
    
    
    
    
    </body>
    </html>
    home.html

    注:

    • 'django.middleware.csrf.CsrfViewMiddleware' 在setting中需要注释掉这一项,否则提交表单时会出错
    • redirect('http://www.baidu.com')             重定向,只能填url;如果填本地url,则为/login,加斜杠
    • render(request, 'login.html',{'error_msg':error_msg})    返回HTML文件
    • <span style="color: red;">{{error_msg}}</span>           error_msg相当于一个变量
    • <form action="/login" method="post"> 和 path('login',views.login): login后面要一样,要不都为login/,要不都为login

     


    路由系统

    https://docs.djangoproject.com/en/1.11/topics/http/urls/

    https://docs.djangoproject.com/en/2.0/topics/http/urls/

    URL配置(URLconf)就像Django 所支撑网站的目录,是URL与视图函数之间的映射表。

    语法

      
    # Django 1.1
    from django.conf.urls import url
    urlpatterns = [
         url(正则表达式, views视图函数,参数,别名),
    ]
    
    # Django 2.0
    from django.urls import path
    urlpatterns = [
        path(正则表达式, views视图函数,参数,别名),
     ]
    
    # 正则表达式:     一个正则表达式字符串
    # views视图函数:  一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
    # 参数:          可选的要传递给视图函数的默认参数(字典形式)
    # 别名:          一个可选的name参数
      
    

    单一路由对应

      
    from django.urls import path
    from cmdb import views
    
    urlpatterns = [
        path('teststate',views.testState),
    ]
      
    

    基于正则的路由

      
    path('^index/(d*)', views.index),
    path('^manage/(?Pw*)/(?Pd*)', views.manage),
      
    # urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。
    # 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
      
    

    APPEND_SLASH配置

    Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但 Django 默认这个参数为 APPEND_SLASH = True。 其作用就是自动在网址结尾加 '/'

    from django.conf.urls import url
    from app01 import views
    
    urlpatterns = [
            url(r'^blog/$', views.blog),
    ]
    # 访问 http://www.example.com/blog 时,默认将网址自动转换为 http://www.example/com/blog/ 。
    # 如果在settings.py中设置了 APPEND_SLASH=False,此时我们再请求 http://www.example.com/blog 时就会提示找不到页面。

    分组命名匹配

    使用分组命名匹配的正则表达式组来捕获URL中的值并以关键字参数形式传递给视图。

      
    # 在Python的正则表达式中,分组命名正则表达式组的语法是(?P<name>pattern),
    # name是组的名称
    # pattern是要匹配的模式。
      
    path('^manage/(?Pw*)/(?Pd*)', views.manage),
      
    

    对于Django2.0以后,urls.py配置不同,如果使用正则匹配,需要导入re_path

    from django.urls import path, re_path
    
    urlpatterns = [
        path(r'admin/', admin.site.urls),
        re_path(r'test/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})', views.test),]

    正则表达式分组匹配(通过圆括号)来捕获URL中的值并以位置参数形式传递给视图。

     
    url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),

    在views 函数中,应当注意形参

    def testState(request, *args, **kwagrs):

    URLconf 在请求的URL 上查找,将它当做一个普通的Python 字符串。不包括GET和POST参数以及域名。

    # http://www.example.com/myapp/ 请求中,URLconf 将查找myapp/。
    # 在http://www.example.com/myapp/?page=3 请求中,URLconf 仍将查找myapp/。
    
    # URLconf 不检查请求的方法。换句话讲,所有的请求方法 —— 同一个URL的POST、GET、HEAD等等 —— 都将路由到相同的函数

    捕获的参数是字符串

    url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    # 传递到视图函数views.year_archive() 中的year 参数永远是一个字符串类型。

    视图函数中指定默认值

    from django.conf.urls import url
    
    from . import views
    
    urlpatterns = [
        url(r'^blog/$', views.page),
        url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
    ]
    
    # views.py中,可以为num指定默认值
    def page(request, num="1"):
        pass
    
    # 第一个模式并没有从URL中捕获任何东西。
    # 如果第一个模式匹配上了,page()函数将使用其默认参数num=“1”,如果第二个模式匹配,page()将使用正则表达式捕获到的num值。

    添加额外的参数

    django.conf.urls.url() 函数可以接收一个可选的第三个参数,它是一个字典,表示想要传递给视图函数的额外关键字参数。

    path(r'^manage/(?P<name>w*)', views.manage,{'id':333}),
    # Django 将调用views.manage(request, name=string, id=333')。

    路由映射设置名称

    pathl(r'^home', views.home, name='home'),           # url匹配模式起名为 home
    pathl(r'^index/(d*)', views.index, name='index'),  # url匹配模式起名为index

    设置名称后,通过如下方式调用:

    # 模板中使用生成URL     {% url 'index' 2012 %} 固定URL:2012 或 {{request.path_info}}  提交表单后返回当前url路径
    # 函数中使用生成URL     reverse('index', args=(2012,))      路径:django.urls.reverse
    # Model中使用获取URL   自定义get_absolute_url() 方法
    
    class NewType(models.Model):
        caption = models.CharField(max_length=16)
    
    
        def get_absolute_url(self):
            """
            为每个对象生成一个URL
            应用:在对象列表中生成查看详细的URL,使用此方法即可!!!
            :return:
            """
            # return '/%s/%s' % (self._meta.db_table, self.id)
            #
            from django.urls import reverse
            return reverse('NewType.Detail', kwargs={'nid': self.id})   # 使用获取URL   自定义get_absolute_url() 方法

    生成路径:

    url(r'^test1',views.test, name='t1')
    url(r'^test2/(d+)/(d+)/',views.test, name='t2')
    url(r'^test3/(?P(pid)d+)/(?P(nid)d+)/',views.test, name='t3')
    
    def func(request, *args, **kwargs):
        from django.urls import reverse
        
        url1 = reverse('t1')                              # test1/
        url2 = reverse('t2', args=(1,2,))           # test2/1/2/
        url3 = reverse('t3', kwagrs=('pid':1, 'nid':2))    # test3/1/2/
    
    # html
    #  {% url 't1' %}
    #  {% url 't2' 1,2 %}
    #  {% url 't3'  pid=1 nid=2%}

    获取请求匹配成功的URL信息: request.resolver_match

    对路由进行分类

    根据app对路由规则进行分类

    url(r'^web/',include('web.urls')),
    # 可以包含其他的URLconfs文件

    命名空间

    即使不同的APP使用相同的URL名称,URL的命名空间模式也可以让你唯一反转命名的URL。

    # project中的urls.py
    from django.conf.urls import url, include
     
    urlpatterns = [
        url(r'^app01/', include('app01.urls', namespace='app01')),
        url(r'^app02/', include('app02.urls', namespace='app02')),
    ]
    
    # app01中的urls.py
    from django.conf.urls import url
    from app01 import views
     
    app_name = 'app01'
    urlpatterns = [
        url(r'^(?P<pk>d+)/$', views.detail, name='detail')
    ]
    
    # app02中的urls.py
    from django.conf.urls import url
    from app02 import views
    
    app_name = 'app02'
    urlpatterns = [
        url(r'^(?P<pk>d+)/$', views.detail, name='detail')
    ]

    以上定义带命名空间的url之后,使用name生成URL时候,应该如下:

    # 模板中使用:
    {% url 'app01:detail' pk=12 %}
    
    # views中的函数中使用
    v = reverse('app01:detail', kwargs={'pk':11})

    视图

      
    request.GET
    request.POST
    request.FILES
    return HttpResponse("字符串")
    return render(request, "HTML模板的路径")
    return redirect('/只能填URL')
      
    

    获取单选框内容

    获取input radio 等单选的内容:

    request.POST.get("radio_name")

    获取复选框内容

    获取checkbox等多选的内容,内容为一个列表:

    request.POST.getlist('checkbox_name')
    

    上传文件

    上传文件,form标签做特殊设置:加上属性enctype="multipart/form-data",如果不加这项属性,默认发的不是文件,则request.FILES.get()为None.

    obj = request.FILES.get()
    obj.name
    f = open(obj.name, 'wb')
    for item in obj.chunks():
      f.write(item)
    f.close

    实例

    views:

    def login(request):
        if request.method == "GET":
            return render(request, 'login.html')
        elif request.method == "POST": 
            v = request.POST.get('gender') 
    v
    = request.POST.getlist('favor')
    obj
    = request.FILES.get('fa') print(obj,type(obj),obj.name) import os file_path = os.path.join('upload', obj.name) f = open(file_path, mode="wb") for i in obj.chunks(): f.write(i) f.close() return render(request, 'login.html') else: return redirect('/index/')

    HTML

    <form action="/login/" method="POST" enctype="multipart/form-data">
            <p>
                <input type="text" name="user" placeholder="用户名" />
            </p>
            <p>
                <input type="password" name="pwd" placeholder="密码" />
            </p>
            <p>
                男:<input type="radio"  name="gender" value="1"/>
                女:<input type="radio" name="gender" value="2"/>
            </p>
            <p>
                男:<input type="checkbox"  name="favor" value="11"/>
                女:<input type="checkbox" name="favor" value="22"/>
            </p>
            <p>
                <select name="city" multiple>
                    <option value="sh">上海</option>
                    <option value="bj">北京</option>
                    <option value="tj">天津</option>
                </select>
            </p>
            <p>
                <input type="file" name="fa"/>
            </p>
            <input type="submit" value="提交"/>
        </form>

    FBV

    FBV:function base view

    url.py:    index  => 函数名
    view.py:   def  函数(request)
    

    CBV

    CBV:class base view

    url.py:  index => 类
    匹配到url后,先调用dispatch方法,再判断get or post继续执行
    

    views:接收到请求后,会先调用dispach方法

    from django.views import View
    
    class Home(View):
        def dispatch(self, request, *args, **kwargs):
            result = super(Home,self).dispatch(request, *args, **kwargs)
            return result
    
        def get(self,request):
            return render(request,'home.html')
    
        def post(self,request):
            return render(request, 'home.html')

    url:

    from cmdb import views
    
    urlpatterns = [
        path('home', views.Home.as_view()),
    ]

    模板

    https://docs.djangoproject.com/en/1.11/ref/templates/builtins/#std:templatetag-for

    两个符号

    <!--   {{}}:   变量相关     -->
    <!--   {% %}:  逻辑相关     -->

    变量

      
    1、在Django的模板语言中按此语法使用:{{ 变量名 }}。
    2、当模版引擎遇到一个变量,它将计算这个变量,然后用结果替换掉它本身。
    3、变量的命名包括任何字母数字以及下划线 ("_")的组合。 变量名称中不能有空格或标点符号。
    4、点(.)在模板语言中有特殊的含义。当模版系统遇到点("."),它将以这样的顺序查询:
         字典查询
         属性或方法查询
         数字索引查询
    
    1、如果计算结果的值是可调用的,它将被无参数的调用。 调用的结果将成为模版的值。
    2、如果使用的变量不存在, 模版系统将插入 string_if_invalid 选项的值, 它被默认设置为'' (空字符串) 。
    

    实例

    def template_test(request):
        l = [11, 22, 33]
        d = {"name": "alex"}
    
        class Person(object):
            def __init__(self, name, age):
                self.name = name
                self.age = age
    
            def dream(self):
                return "{} is dream...".format(self.name)
    
        Alex = Person(name="Alex", age=34)
        Egon = Person(name="Egon", age=9000)
        Eva_J = Person(name="Eva_J", age=18)
    
        person_list = [Alex, Egon, Eva_J]
        return render(request, "template_test.html", {"l": l, "d": d, "person_list": person_list})
    view
     1 <body>
     2     <!--{# 取l中的第一个参数 #}-->
     3     {{ l.0 }}
     4     <br />
     5     {# 取字典中key的值 #}
     6     {{ d.name }}
     7     <br />
     8     {# 取对象的name属性 #}
     9     {{ person_list.0.name }}
    10     <br />
    11     {# .操作只能调用不带参数的方法 #}
    12     {{ person_list.0.dream }}
    13 </body>
    template.html

    Filters:过滤器

    在Django的模板语言中,通过使用过滤器来改变变量的显示。

    语法:使用管道符"|"来应用过滤器。

      
    # {{ value|filter_name:参数 }}
    
    {{ name|lower }}
    # 会将name变量应用lower过滤器之后再显示它的值。lower在这里的作用是将文本全都变成小写。
    

    注意

    • 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。
    • 过滤器可以接受参数,例如:{{ sss|truncatewords:30 }},这将显示sss的前30个词。
    • 过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,如:{{ list|join:', ' }}
    • '|'左右没有空格没有空格没有空格

    Django内置过滤器

    default

    # 如果一个变量是false或者为空,使用给定的默认值。 否则,使用变量的值。
    {{ value|default:"nothing"}}
    

    length

    # 返回值的长度,作用于字符串和列表。
    {{ value|length }}
    # 返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.

    filesizeformat

    # 将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。
    {{ value|filesizeformat }}
    # 如果 value 是 123456789,输出将会是 117.7 MB。

    slice

    # 切片
    {{value|slice:"2:-1"}}

    date

    # 格式化时间
    {{ value|date:"Y-m-d H:i:s"}}

    truncatechars

    # 如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
    # 参数:截断的字符数
    {{ value|truncatechars:9}}

    truncatewords

    # 在一定数量的字后截断字符串。
    {{ value|truncatewords:9}}

    cut

    # 移除value中所有的与给出的变量相同的字符串
    {{ value|cut:' ' }}
    # 如果value为'i love you',那么将输出'iloveyou'.

    join

    # 使用字符串连接列表,例如Python的str.join(list)

    自定义filter

    自定义过滤器只是带有一个或两个参数的Python函数:

    # 变量(输入)的值 - -不一定是一个字符串
    # 参数的值 - 这可以有一个默认值,或完全省略
    # 例如,在过滤器{{var | foo:'bar'}}中,过滤器foo将传递变量var和参数“bar”。

    在哪定义filter代码:

      
    app01/
        __init__.py
        models.py
        templatetags/         # 在app01下面新建一个package package
            __init__.py
            app01_filters.py  # 建一个存放自定义filter的文件
        views.py
      
    

    如何编写自定义filter

      
    from django import template
    register = template.Library()
    
    @register.filter(name="say_hello")
    def say_hello(value):
        return "hello {}".format(value)
      
    

    如何使用自定义filter

      
    {# 先导入我们自定义filter那个文件 #}
    {% load app01_filters %}
    
    {# 使用我们自定义的filter #}
    {{ d.name|say_hello }}
      
    

    for循环

    <ul>
    {% for user in user_list %}
        <li>{{ user.name }}</li>
    {% endfor %}
    </ul>

    for ... empty

    <ul>
    {% for user in user_list %}
        <li>{{ user.name }}</li>
    {% empty %}
        <li>空空如也</li>
    {% endfor %}
    </ul>

    for语句在模板里的应用

    for循环与table结合使用:在html中获取字典或列表里面的值,可以通过row.key或row.1等方式获得

    # views代码
    user_list = [
    {'username':'a','email':'aaaaaa','gender':'M'},
    {'username':'b','email':'bbbbbb','gender':'M'},
    {'username':'c','email':'cccccc','gender':'F'}
    ]
    
    return render(request,'home.html',{'user_list':user_list})
    
    # HTML
    <table>
    {% for row in user_list %}
    <tr>
    <td>{{row.username}}</td>
    <td>{{row.gender}}</td>
    <td>{{row.email}}</td>
    </tr>
    {% endfor %}
    </table>

    模板语言访问字典

    USER_DICT = {
    '1': {'name': 'root1', 'email': 'root@live.com'},
    '2': {'name': 'root2', 'email': 'root@live.com'},
    }
    
    # HTML
    {{user_dict.k1}}
    
    {%for k,v in user_dict.items%}
    <li><{{k}}-{{v}}/li>
    {%endfor%}
    
    {%for k in user_dict.keys%}
    <li><{{k}}/li>
    {%endfor%}
    
    {%for v in user_dict.values%}
    <li><{{v}}/li>
    {%endfor%}

    条件判断

    if ... else/ if ... elif ... else

    {% if user_list %}
      用户人数:{{ user_list|length }}
    {% elif black_list %}
      黑名单数:{{ black_list|length }}
    {% else %}
      没有用户
    {% endif %}

    注: if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。

    with

    定义一个中间变量,多用于给一个复杂的变量起别名。

    {% with total=business.employees.count %}
        {{ total }} employee{{ total|pluralize }}
    {% endwith %}
    
    {% with business.employees.count as total %}
        {{ total }} employee{{ total|pluralize }}
    {% endwith %}

    注:  等号左右不要加空格。

    注释

    {# ... #}

    模板语言注意事项

      
    1. Django的模板语言不支持连续判断,即不支持以下写法
        {% if a > b > c %}
            ...
        {% endif  }   %
    
    2. Django的模板语言中属性的优先级大于方法
        def xx(request):
            d = {"a": 1, "b": 2, "c": 3, "items": "100"}
            return render(request, "xx.html", {"data": d})
    如上,我们在使用render方法渲染一个页面的时候,传的字典d有一个key是items并且还有默认的 d.items() 方法,此时在模板语言中: {{ data.items }}{{ data.items }},默认会取d的items key的值。
      
    

     


    ORM操作

    对象关系映射(Object Relational Mapping,简称ORM)模式通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。

    ORM在业务逻辑层和数据库层之间充当了桥梁的作用。

    Django中ORM的配置

    https://docs.djangoproject.com/en/2.0/topics/db/queries/

    setting.py文件配置:

      
    DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.mysql",
            "NAME": "你的数据库名称",  # 需要自己手动创建数据库
            "USER": "数据库用户名",
            "PASSWORD": "数据库密码",
            "HOST": "数据库IP",
            "POST": 3306
        }
    }
      
    

    Django项目的__init__.py文件配置:

      
    # 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替
    # 如下设置放置的与project同名的配置的 __init__.py文件中
    import pymysql
    
    pymysql.install_as_MySQLdb()
      
    

    字段

      
    AutoField:     int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。
    IntegerField:  一个整数类型,范围在 -2147483648 to 2147483647。
    CharField:     字符类型,必须提供max_length参数, max_length表示字符长度。
    DateField:     日期字段,日期格式  YYYY-MM-DD,相当于Python中的datetime.date()实例。
    DateTimeField: 日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例。
      
    

    其他字段:

    AutoField(Field)
            - int自增列,必须填入参数 primary_key=True
    
        BigAutoField(AutoField)
            - bigint自增列,必须填入参数 primary_key=True
    
            注:当model中如果没有自增列,则自动会创建一个列名为id的列
            from django.db import models
    
            class UserInfo(models.Model):
                # 自动创建一个列名为id的且为自增的整数列
                username = models.CharField(max_length=32)
    
            class Group(models.Model):
                # 自定义自增列
                nid = models.AutoField(primary_key=True)
                name = models.CharField(max_length=32)
    
        SmallIntegerField(IntegerField):
            - 小整数 -32768 ~ 32767
    
        PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
            - 正小整数 0 ~ 32767
        IntegerField(Field)
            - 整数列(有符号的) -2147483648 ~ 2147483647
    
        PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
            - 正整数 0 ~ 2147483647
    
        BigIntegerField(IntegerField):
            - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807
    
        自定义无符号整数字段
    
            class UnsignedIntegerField(models.IntegerField):
                def db_type(self, connection):
                    return 'integer UNSIGNED'
    
            PS: 返回值为字段在数据库中的属性,Django字段默认的值为:
                'AutoField': 'integer AUTO_INCREMENT',
                'BigAutoField': 'bigint AUTO_INCREMENT',
                'BinaryField': 'longblob',
                'BooleanField': 'bool',
                'CharField': 'varchar(%(max_length)s)',
                'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
                'DateField': 'date',
                'DateTimeField': 'datetime',
                'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
                'DurationField': 'bigint',
                'FileField': 'varchar(%(max_length)s)',
                'FilePathField': 'varchar(%(max_length)s)',
                'FloatField': 'double precision',
                'IntegerField': 'integer',
                'BigIntegerField': 'bigint',
                'IPAddressField': 'char(15)',
                'GenericIPAddressField': 'char(39)',
                'NullBooleanField': 'bool',
                'OneToOneField': 'integer',
                'PositiveIntegerField': 'integer UNSIGNED',
                'PositiveSmallIntegerField': 'smallint UNSIGNED',
                'SlugField': 'varchar(%(max_length)s)',
                'SmallIntegerField': 'smallint',
                'TextField': 'longtext',
                'TimeField': 'time',
                'UUIDField': 'char(32)',
    
        BooleanField(Field)
            - 布尔值类型
    
        NullBooleanField(Field):
            - 可以为空的布尔值
    
        CharField(Field)
            - 字符类型
            - 必须提供max_length参数, max_length表示字符长度
    
        TextField(Field)
            - 文本类型
    
        EmailField(CharField):
            - 字符串类型,Django Admin以及ModelForm中提供验证机制
    
        IPAddressField(Field)
            - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
    
        GenericIPAddressField(Field)
            - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
            - 参数:
                protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
                unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"
    
        URLField(CharField)
            - 字符串类型,Django Admin以及ModelForm中提供验证 URL
    
        SlugField(CharField)
            - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
    
        CommaSeparatedIntegerField(CharField)
            - 字符串类型,格式必须为逗号分割的数字
    
        UUIDField(Field)
            - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
    
        FilePathField(Field)
            - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
            - 参数:
                    path,                      文件夹路径
                    match=None,                正则匹配
                    recursive=False,           递归下面的文件夹
                    allow_files=True,          允许文件
                    allow_folders=False,       允许文件夹
    
        FileField(Field)
            - 字符串,路径保存在数据库,文件上传到指定目录
            - 参数:
                upload_to = ""      上传文件的保存路径
                storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
    
        ImageField(FileField)
            - 字符串,路径保存在数据库,文件上传到指定目录
            - 参数:
                upload_to = ""      上传文件的保存路径
                storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
                width_field=None,   上传图片的高度保存的数据库字段名(字符串)
                height_field=None   上传图片的宽度保存的数据库字段名(字符串)
    
        DateTimeField(DateField)
            - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
    
        DateField(DateTimeCheckMixin, Field)
            - 日期格式      YYYY-MM-DD
    
        TimeField(DateTimeCheckMixin, Field)
            - 时间格式      HH:MM[:ss[.uuuuuu]]
    
        DurationField(Field)
            - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
    
        FloatField(Field)
            - 浮点型
    
        DecimalField(Field)
            - 10进制小数
            - 参数:
                max_digits,小数总长度
                decimal_places,小数位长度
    
        BinaryField(Field)
            - 二进制类型
    字段

    参数

      
    null      用于表示某个字段可以为空。
    unique    如果设置为unique=True 则该字段在此表中必须是唯一的 。
    db_index  如果db_index=True 则代表着为此字段设置数据库索引。
    default   为该字段设置默认值。
      
    

    其他参数:

    null                数据库中字段是否可以为空
        db_column           数据库中字段的列名
        db_tablespace
        default             数据库中字段的默认值
        primary_key         数据库中字段是否为主键
        db_index            数据库中字段是否可以建立索引
        unique              数据库中字段是否可以建立唯一索引
        unique_for_date     数据库中字段【日期】部分是否可以建立唯一索引
        unique_for_month    数据库中字段【月】部分是否可以建立唯一索引
        unique_for_year     数据库中字段【年】部分是否可以建立唯一索引
    
        verbose_name        Admin中显示的字段名称
        blank               Admin中是否允许用户输入为空
        editable            Admin中是否可以编辑
        help_text           Admin中该字段的提示信息
        choices             Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
                            如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)
    
        error_messages      自定义错误信息(字典类型),从而定制想要显示的错误信息;
                            字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
                            如:{'null': "不能为空.", 'invalid': '格式错误'}
    
        validators          自定义错误验证(列表类型),从而定制想要的验证规则
                            from django.core.validators import RegexValidator
                            from django.core.validators import EmailValidator,URLValidator,DecimalValidator,
                            MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
                            如:
                                test = models.CharField(
                                    max_length=32,
                                    error_messages={
                                        'c1': '优先错信息1',
                                        'c2': '优先错信息2',
                                        'c3': '优先错信息3',
                                    },
                                    validators=[
                                        RegexValidator(regex='root_d+', message='错误了', code='c1'),
                                        RegexValidator(regex='root_112233d+', message='又错误了', code='c2'),
                                        EmailValidator(message='又错误了', code='c3'), ]
                                )
    参数

    元信息

      
    class UserInfo(models.Model):
            nid = models.AutoField(primary_key=True)
            username = models.CharField(max_length=32)
            class Meta:
                # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
                db_table = "table_name"
    
                # 联合索引
                index_together = [
                    ("pub_date", "deadline"),
                ]
    
                # 联合唯一索引
                unique_together = (("driver", "restaurant"),)
    
                # admin中显示的表名称
                verbose_name
    
                # verbose_name加s
                verbose_name_plural
    

    拓展

    1.触发Model中的验证和错误提示有两种方式:
            a. Django Admin中的错误信息会优先根据Admiin内部的ModelForm错误信息提示,如果都成功,才来检查Model的字段并显示指定错误信息
            b. 调用Model对象的 clean_fields 方法,如:
                # models.py
                class UserInfo(models.Model):
                    nid = models.AutoField(primary_key=True)
                    username = models.CharField(max_length=32)
    
                    email = models.EmailField(error_messages={'invalid': '格式错了.'})
    
                # views.py
                def index(request):
                    obj = models.UserInfo(username='11234', email='uu')
                    try:
                        print(obj.clean_fields())
                    except Exception as e:
                        print(e)
                    return HttpResponse('ok')
    
               # Model的clean方法是一个钩子,可用于定制操作,如:上述的异常处理。
    
        2.Admin中修改错误提示
            # admin.py
            from django.contrib import admin
            from model_club import models
            from django import forms
    
    
            class UserInfoForm(forms.ModelForm):
                username = forms.CharField(error_messages={'required': '用户名不能为空.'})
                email = forms.EmailField(error_messages={'invalid': '邮箱格式错误.'})
                age = forms.IntegerField(initial=1, error_messages={'required': '请输入数值.', 'invalid': '年龄必须为数值.'})
    
                class Meta:
                    model = models.UserInfo
                    # fields = ('username',)
                    fields = "__all__"
    
    
            class UserInfoAdmin(admin.ModelAdmin):
                form = UserInfoForm
    
    
            admin.site.register(models.UserInfo, UserInfoAdmin)
    拓展
    对应关系:
        'AutoField': 'integer AUTO_INCREMENT',
        'BigAutoField': 'bigint AUTO_INCREMENT',
        'BinaryField': 'longblob',
        'BooleanField': 'bool',
        'CharField': 'varchar(%(max_length)s)',
        'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
        'DateField': 'date',
        'DateTimeField': 'datetime',
        'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
        'DurationField': 'bigint',
        'FileField': 'varchar(%(max_length)s)',
        'FilePathField': 'varchar(%(max_length)s)',
        'FloatField': 'double precision',
        'IntegerField': 'integer',
        'BigIntegerField': 'bigint',
        'IPAddressField': 'char(15)',
        'GenericIPAddressField': 'char(39)',
        'NullBooleanField': 'bool',
        'OneToOneField': 'integer',
        'PositiveIntegerField': 'integer UNSIGNED',
        'PositiveSmallIntegerField': 'smallint UNSIGNED',
        'SlugField': 'varchar(%(max_length)s)',
        'SmallIntegerField': 'smallint',
        'TextField': 'longtext',
        'TimeField': 'time',
        'UUIDField': 'char(32)',
    字段对应

    时间字段

      
    DatetimeField、DateField、TimeField   这个三个时间字段,都可以设置如下属性。
    auto_now_add  配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。
    auto_now      配置上auto_now=True,每次更新数据记录的时候会更新该字段。
    1. 下面方式修改数据auto_now不生效
    # obj = UserGroup.objects.filter(id=1).update(caption='CEO')
    2. 使auto_now生效使用如下:
    # obj = UserGroup.objects.filter(id=1).first()
    # obj.caption = "CEO"
    # obj.save()
      
    

    连表结构

      
    一对多:models.ForeignKey(其他表)
          user_group=models.ForeignKey('UserGroup',to_field='uid',default=1)   关联UserGroup表的uid字段
          创建用户:
            models.UserInfo.objects.create(user_group=models.UserGroup.objects.filter(id=1).frist())
           或: models.UserInfo.objects.create(user_group_id=1)
          外键查找关联表数据:
            uid=models.UserInfo.objects.filter(id=1).first().user_group_id        查找组id
            user_group=models.UserInfo.objects.filter(id=1).first().user_group         返回一个UserGroup对象,可查找UserGroup表的所有信息 
    多对多:models.ManyToManyField(其他表)
    一对一:models.OneToOneField(其他表)
      
    

    表的基本操作

      
    # 增    # models.Tb1.objects.create(c1='xx', c2='oo')  增加一条数据,可以接受字典类型数据 **kwargs
        # obj = models.Tb1(c1='xx', c2='oo')
        # obj.save()
    # 查    # models.Tb1.objects.get(id=123)         # 获取单条数据,不存在则报错(不建议)
        # data= models.Tb1.objects.all()             # 获取全部数据,QuerySet类型,[obj1,obj2....]
        data.query()                  # 将查询语句翻译成SQL查询语句 select * from tb # models.Tb1.objects.filter(name='seven') # 获取指定条件的数据 # models.Tb1.objects.all().values('字段1','字段2'...) # 获取全部数据,返回QuerySet类型[{'字段1':value,'字段2':value},{},{}] # models.Tb1.objects.all().values_list('字段1','字段2'..) # 获取全部数据,返回QuerySet类型[(value1,value2..),()...] # 删 # models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据 # 改 # models.Tb1.objects.filter(name='seven').update(gender='0') # 将指定条件的数据更新,均支持 **kwargs # obj = models.Tb1.objects.get(id=1) # obj.c1 = '111' # obj.save() # 修改单条数据   

    操作表常用属性

      
    all():                 查询所有结果
    filter(**kwargs):      它包含了与所给筛选条件相匹配的对象
    get(**kwargs):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
    exclude(**kwargs):     它包含了与所给筛选条件不匹配的对象
    values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列
    values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
    order_by(*field):      对查询结果排序
    reverse():             对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法)。
    distinct():            从返回结果中剔除重复纪录(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重。)
    count():              返回数据库中匹配查询(QuerySet)的对象数量。
    first():              返回第一条记录,若没有则为None。可以和filter结合起来使用
    last():               返回最后一条记录
    exists():             如果QuerySet包含数据,就返回True,否则返回False
      
    

    参考:

    https://www.cnblogs.com/liwenzhou/p/9959979.html

     


  • 相关阅读:
    福大软工 · BETA 版冲刺前准备(团队)
    福大软工 · 第十一次作业
    Alpha 冲刺 (9/10)
    Alpha 冲刺 (8/10)
    Alpha 冲刺 (7/10)
    Alpha 冲刺 (6/10)
    Alpha 冲刺 (5/10)
    Alpha 冲刺 (4/10)
    福大软工1816 · 团队现场编程实战(抽奖系统)
    阿里八八β阶段Scrum(5/5)
  • 原文地址:https://www.cnblogs.com/gareth-yu/p/9688991.html
Copyright © 2020-2023  润新知