• web框架之Django(python3入门)


    一、初识Django

    Django 是一个web框架
    web框架的本质
    - web框架的本质就是一个socket服务端(帮你处理了socket,让你只需要专注于逻辑处理) 
    - 符合wsig协议的web服务器 b
    /s架构:浏览器---服务器,本质也是c/s架构

    二、HTTP协议

    http请求协议:
        请求首行:
            请求的方法 空格 请求地址 空格 请求协议
                GET        /index     HTTP/1.1
    
        请求头:
            (key:value的形式展现)
            'Connection: keep-alive
    
            Pragma: no-cache
    
            Cache-Control: no-cache
    
            Upgrade-Insecure-Requests: 1
    
            User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36
    
            Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    
            Accept-Encoding: gzip, deflate, br
    
            Accept-Language: zh-CN,zh;q=0.9
    
    '
        请求体:
            可以携带data数据(向服务器发送的数据)
            如:用户名/密码等信息
    http请求协议
    http响应协议:
        响应首行:
            HTTP/1.1 200 OK 
    
        响应头:
            key:value 
    
            xx:xx 
    
            yy:yy 
    
        响应体:
            响应数据...
    http响应协议

    三、Web框架简介

    把一个请求拆分成几部分,每个部分干相同的事
    Python中的web框架:
        Django:大而全的框架
        flask:轻量级 微框架
        Tornado:高性能的框架
    MVC架构
        M:模型层,model
        V:视图,对应django中的T
        C:控制器,根据用户的请求地址,执行某些代码
    
    MTV架构
        django是MTV架构的
            M:模型层,数据操作层,model
            T:模板层,template
            V:视图层,view
                路由控制+视图层 是mvc的c层

    四、Django的安装和使用

    - 安装Django的三种方式:
        1 在cmd窗口下:pip3 install django == 1.11.9
        2 在pycharm的Terminal窗口下: pip3 install django == 1.11.9
        3 在pycharm - setting中安装,选择版本号: 1.11.9
    - 卸载Django
        1 pip3 unistall django
        2 在pycharm-setting中进行卸载
    - 安装完成后dgango后会在python36Scripts,会多一个django-admin.exe
    - 创建Django项目
        命令行 django-admin startproject myfirstdjango(了解就行)

    五、Django项目的目录结构

    - manage.py 项目入口 运行项目需要用到
    - templates文件夹:放模板文件,放html模板
    
    - 项目名的文件夹(*****现阶段需要记住的)
        setting.py 项目配置文件(整个项目的配置信息)    *****
        urls.py 路由和函数的映射关系  ***** 
        wsgi.py django框架帮咱写的socket
    
    - app名字的文件夹
        migrations 数据库迁移相关的,记录变化的文件
        admin.py 后台管理相关(知道就行)
        apps.py app的配置信息(app自己的配置信息)
        models.py 数据库相关,函数取数据用的 *****
        tests.py 测试相关的
        views.py 视图(业务逻辑)   *****
    
    - app的概念(每个django项目至少有一个app!!!)
        大学 ---- django项目
        xx学院 ---- 一个个的app
        创建app的命令(新建app01)
            python3 manage.py startapp app01
    目录结构

    六、运行Django项目

    python3 manage.py runserver
    重点*****
        安装django
        创建django项目
        创建app
        运行项目
    第一种方式-命令行
    - pycharm中创建项目 输入项目名称+自定义app名称+解释器选择
    - pycharm中运行项目 绿色箭头运行
    第二种方式-用pycharm

    七、Django框架的简单使用

    - django项目中重点需要关注的文件夹:
        - urls.py
        - views.py
        - models.py
    Django项目文件夹中重点关注的文件
    1 在浏览器输入 http://127.0.0.1/index 并在页面显示hello django
        > 首先在views.py中键入新手三件套
            from django.shortcuts import render
            from django.shortcuts import HttpResponse
            from django.shortcuts import redirect
        > 其次在views.py中输入index页面的函数
            def index(request):
                return HttpResponse('hello django')     #可以向浏览器返回字符串
        > 接着在urls.py中新增路由和函数的映射关系
            from app01 import views
            urlpatterns = [
                url(r'^index/', views.index),
            ]
        > 接着点击绿色箭头运行该项目
        > 最后打开浏览器输入 http://127.0.0.1/index查看页面显示内容
    Django框架的简单使用之一
    2 在浏览器输入 http://127.0.0.1/index 向浏览器返回一个页面
        > 首先在views.py中键入新手三件套
            from django.shortcuts import render
            from django.shortcuts import HttpResponse
            from django.shortcuts import redirect
        > 其次在views.py中输入index页面的函数
            def index(request):
                #render是一个方法,第一个参数传request对象,第二个参数是模板文件的名字
                return render(request,'index.html')   
        > 接着在templates文件夹中新建html页面,命名问index.html,并在页面中随意写一些内容
            <body>
            <h1>django的index页面</h1>
            <a href="https://baidu.com">点我看美女</a>
            </body>
        > 在浏览器输入 http://127.0.0.1/index 查看结果
    Django框架的简单使用之二
    3 在浏览器输入 http://127.0.0.1/index 重定向到www.baidu.com
        > 首先在views.py中键入新手三件套
            from django.shortcuts import render
            from django.shortcuts import HttpResponse
            from django.shortcuts import redirect
        > 其次在views.py中输入index页面的函数
            def index(request):
                # 返回重定向
                # 1xx 接受的请求正在处理,信息性状态码
                # 2xx 成功状态码
                # 3xx 重定向状态码
                # 4xx 客户端错误状态码
                # 5xx 服务器错误状态码
                return redirect('https://www.baidu.com')
        > 在浏览器输入 http://127.0.0.1/index 查看结果
    Django框架的简单使用之三

    八、Django框架层面分析

    - 路由层:
    - 基本使用
        # url是一个函数,函数参数,第一个参数是一个正则表达式
        # 用户请求的路径只有匹配成功,才去执行后面的函数
        url(r'^index$,views.index)
    路由层
    - 无名分组
        url(r'^index/(d+)/(d+)', views.index)
        括号内的内容会被分组区分开,当作一个个参数,传入到都好后面的views.index视图函数中
        视图函数会接受这些参数
    无名分组
    - 有名分组
        url(r'^index/(?P<cc>d+)/(?P<ee>d+)', views.index)
        括号内的内容会被分组分出来,当作参数,以key:value的形式传入后面的视图函数
        视图函数会接受这些参数
    有名分组
    - 反向解析
        1 补充重定向
        2 反向解析,通过名字,反解出名字对应的url地址
            例1:应用在视图函数中
            urls.py  
                url(r'^test222/$', views.test,name='ttt')
    
            views.py
                from django.shortcuts import reverse
                def index(request):
                    url = reverse('ttt')
                    return redirect(url)
    
            例2:应用在模板中
                <a href="{% url 'ttt' %}">点我看新美女</a>
    反向解析
    - 路由分发
        例如:
            使用命令创建app02  python3 manage.py startapp app02
            ### 注意,新建app一定要在setting.py中进行注册
                ### 注册app,两种方式都可以,官方推荐使用下面的第一种
                找到INSTALLED_APPS = [],并在其中添加以下命令,
                1 'app02.apps.App01Config',
                2 'app02',
    
            使用方式:
                1 在项目文件夹的urls.py中,控制不同app的urls.py
                    urlpatterns = [
                    url(r'app01/',include('app01.urls')),   #正则部分不能加结束符$
                    url(r'app02/',include('app02.urls')),   #正则部分不能加结束符$
                    ]
                2 在app01文件夹中的urls.py中,控制本app的路由
                    urlpatterns = [
                        url(r'^app01test/', views.test),
                    ]
                3 在app02文件夹中的urls.py中,控制本app的路由
                    urlpatterns = [
                        url(r'^app02test/', views.test),    #给该条路由重命名为ttt
                    ]
                4 在不同app的文件夹中的views.py文件中输入定义test函数
    
                5 在web页面中输入测试:http://127.0.0.1:8000/app01/app01test/
                                    http://127.0.0.1:8000/app02/app02test/
    路由分发
    - django2.0版本的path
        - django2.x的re_path就是1.x的url
        - django2.x的path是新增的功能
            path('准确路径',view.test,name='ttt')
    Django2.x版本的path了解
    -视图层
        - 以get形式传的参数,直接拼接在路径后面,例如:http://127.0.0.1:8000/index/?name=lich&age=18
            这种方式的传参,并没有把数据放在http协议的请求体中,而是直接放到请求头部了
            (post提交的数据,才放在请求体中)
    
        - 请求对象request
            # request是一个请求对象
    
            # 请求方法
            print(request.method)   # 再浏览器里发的请求都是GET
    
            # 请求地址
            print(request.path) #访问的地址是/index/
    
            # 请求全路径
            print(request.get_full_path())  # <QueryDict: {}>当作一个字典
    
            #请求get形式传参
            print(request.GET)  #没有传参<QueryDict: {}>,所以为空
            # http://127.0.0.1:8000/index/?name=lich&age=18 这是传参方式
    
            # 请求体的内容
            print(request.body)
    
            # 以post形式传的参数
            # print(request.POST)
    
            # 查看请求源IP地址   REMOTE_ADDR 客户端请求源IP的字段,可以从这个字典中取出
            {'PATH': '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/aria2/bin:/Applications/Wireshark.app/Contents/MacOS', 'PYTHONPATH': '/Applications/PyCharm.app/Contents/helpers/pycharm_matplotlib_backend:/Users/lich/PycharmProjects/MySecondDjangProj', 'SHELL': '/bin/bash', 'PYTHONIOENCODING': 'UTF-8', 'VERSIONER_PYTHON_PREFER_32_BIT': 'no', 'USER': 'lich', 'TMPDIR': '/var/folders/z6/sc42tfkd71bbq228v7nc_c1w0000gn/T/', 'SSH_AUTH_SOCK': '/private/tmp/com.apple.launchd.cDNseej7iN/Listeners', 'DJANGO_SETTINGS_MODULE': 'MySecondDjangProj.settings', 'XPC_FLAGS': '0x0', 'PYTHONUNBUFFERED': '1', 'VERSIONER_PYTHON_VERSION': '2.7', '__CF_USER_TEXT_ENCODING': '0x1F5:0x19:0x34', 'Apple_PubSub_Socket_Render': '/private/tmp/com.apple.launchd.xzQeRBq6rT/Render', 'LOGNAME': 'lich', 'LC_CTYPE': 'zh_CN.UTF-8', 'XPC_SERVICE_NAME': 'com.jetbrains.pycharm.120044', 'PWD': '/Users/lich/PycharmProjects/MySecondDjangProj', 'PYCHARM_HOSTED': '1', 'HOME': '/Users/lich', 'PYCHARM_MATPLOTLIB_PORT': '61214', '__PYVENV_LAUNCHER__': '/usr/local/Cellar/python/3.6.5/bin/python3.6', 'TZ': 'UTC', 'RUN_MAIN': 'true', 'SERVER_NAME': '1.0.0.127.in-addr.arpa', 'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_PORT': '8000', 'REMOTE_HOST': '', 'CONTENT_LENGTH': '17', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'WSGIServer/0.2', 'REQUEST_METHOD': 'POST', 'PATH_INFO': '/login/', 'QUERY_STRING': '', 'REMOTE_ADDR': '127.0.0.1', 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'HTTP_HOST': '127.0.0.1:8000', 'HTTP_CONNECTION': 'keep-alive', 'HTTP_CACHE_CONTROL': 'max-age=0', 'HTTP_ORIGIN': 'http://127.0.0.1:8000', 'HTTP_UPGRADE_INSECURE_REQUESTS': '1', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36', 'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'HTTP_REFERER': 'http://127.0.0.1:8000/login/', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9', 'wsgi.input': <_io.BufferedReader name=5>, 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.version': (1, 0), 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>}
    
    
    
        ### 注意:遇到403Forbidden,优先跑到setting.py中
                #先注释掉下面这行,等讲到中间件的时候再展开讨论
                # 'django.middleware.csrf.CsrfViewMiddleware',
    视图层
    - 模版层
        - DTL:Django Template Language - django的模版语言
        - {{ }}
            1,通过 "."来做深度查询
            例如:
                views.py配置
                    import time
                    class Person():
                        def __init__(self,name):
                            self.name = name
    
                    def index(request):
                        #例1:
                        # ctime = str(time.time())
                        #
                        # return render(request,'new_index.html',{'time':ctime})
    
                        #例2:
                        ctime = str(time.time())
                        dic = {
                            'name':'lich',
                            'age':18
                        }
                        li = [1,2,3,4,5]
    
                        def test():
                            return '我是个函数'
    
                        #生成对象
                        lich = Person('lich')
    
                        #locals() 会把该函数中的所有的变量,构造成字典并传送到模板中
                        return render(request,'new_index.html',locals())
    
                new_index.html配置
                    <body>
                        {# 模版语言例1: #}
                        <h1>模版语言之变量</h1>
                        <p>{{ ctime }}</p>
                        <p>{{ dic }}</p>
    
                        {#模板语法和python语法有点区别,直接用.就可以取值#}
                        {#在模板中写的变量,相当于print该变量,变量都是字符串#}
                        <p>{{ dic.name }}</p>
                        <p>{{ dic.age }}</p>
                        <p>{{ li }}</p>
    
                        {#取第一个值li.0#}
                        <p>{{ li.0 }}</p>
                        <p>{{ li.0 }}|{{ li.1 }}|{{ li.2 }}</p>
    
                        <p><a href="{{ dic.name }}">{{ li.3 }}</a></p>
    
                        {#执行一个函数,不要加括号#}
                        <p>{{ test }}</p>
    
                        {#打印了一个对象的内存地址#}
                        <p>{{ lich }}</p>
    
                        {#对象取值#}
                        <p>{{ lich.name }}</p>
                    </body>
    
                urls.py配置
                    urlpatterns = [
                        # url(r'^index/$', views.index),   #正则部分不能加结束符$
                        # url(r'^login/$', views.login),   #正则部分不能加结束符$
                        url(r'^index/$', views.index),   #正则部分不能加结束符$
    
                    ]
    
            2,过滤器
                语法: {{obj|filter_name:param}}   变量名|过滤器方法名称:参数
                ### 记住date 和 safe 就可以了(xss作为了解)
    
    
    
                    views.py配置
                        import time
                        import datetime
    
                        class Person():
                            def __init__(self,name):
                                self.name = name
    
                        def index(request):
                            #例1:
                            # ctime = str(time.time())
                            #
                            # return render(request,'new_index.html',{'time':ctime})
    
                            #例2:
                            ctime = str(time.time())
                            dic = {
                                'name':'lich',
                                'age':18
                            }
                            li = [1,2,3,4,5]
    
                            def test():
                                return '我是个函数'
    
                            #生成对象
                            lich = Person('lich')
    
                            count = 10
                            i = 1024
    
                            b = False
                            a = True
    
                            dat = datetime.datetime.now()
    
                            ss = '<input type="text" name="name">'
    
                            xss = '<script>alert(123)</script>'
    
                            #locals() 会把该函数中的所有的变量,构造成字典并传送到模板中
                            return render(request,'new_index.html',locals())
    
                    nex_index.html配置
                        {#过滤器,相当于将count所代表的数值+1#}   #记住safe date 其他的了解即可
                        {{ count|add:1 }}
    
                        <p>{{ b }}</p>
                        <p>{{ b|default:'bbbbb' }}</p>
                        <p>{{ a|default:'aaaaa' }}</p>
    
                        {#列表长度计算#}
                        <p>li的长度为{{ li|length }}</p>
    
                        {#通过filesizeformat进行单位计量转换#}
                        <p>{{ i|filesizeformat }}</p>
    
                        {#时间格式化过滤器#}
                        <p>{{ dat }}</p>
                        <p>{{ dat|date:'Y-m-d H:i:s' }}</p>
    
                        {#可以在views.py写一些 html的语法,如果要在web显示出来功能,则需要使用safe#}
                        <p>{{ ss }}</p>
                        <p>{{ ss|safe }}</p>
    
                        {#跨站脚本攻击演示,django已经帮我们处理了这个,如果我们认为是安全的脚本,则使用safe#}
                        <p>{{ xss|safe }}</p>
    模版层-{{}}的用法
    未完待续
    模版层-{% %}的用法

     模板语言用法。。。

    - ORM
        ORM是什么?
            不是django独有或者python独有的
            对象关系映射
        python中主流的几个ORM框架
            django的orm(django已经封装好了,必须在django中使用)
            sqlAchemy 第三方的orm框架(这个可以单独拿出来使用)--- Flask框架并没有orm,会用到sqlAchemy
            自己写
        orm不能创建数据库,只能创建表,删除表,新增字段,删除字段
        通过orm创建user表
    
        第一步 在settings.py配置
            DATABASES={
                'ENGINE':'django.db.backends.mysql',
                'NAME':'数据库名字',
                'HOST':'mysql IP''PORT':3306'USER':'数据库用户名''PASSWORD':'数据库密码'
            }    
        第二步 链接数据库,操作数据库的模块(pymysql)
            - mysqlDB 只能python 2.x用(django内置这个模块)
            - pymysql python2.x 和3.x 都可以用
            - 所以需要在__init__.py下写一行代码(一般情况 写在app下面的__init__中)
                import pymysql
                # 让pymysql替换掉原来django中内置的mysqldb的地方,以后操作mysql,就用pymysql这个模块
                pymysql.install_as_MySQLdb()
    
        第三步 创建一个表(在models.py中创建新表)
    
            # 创建一个user表,在orm中,其实就是写一个类
            class User(models.Model):
                # 在这个类中,写入需要创建的字段
    
                # id字段,自增,int类型,是主键
                id = models.AutoField(primary_key=True)
    
                # name字段,varchar类型 ,长度32
                name = models.CharField(max_length=32)
    
                # pwd字段,varchar类型 ,长度32,可以为空
                pwd = models.CharField(max_length=32, null=True)
    
        第四步:
            把新建表同步到数据库,django项目中的migrations文件夹存放数据库迁移的记录
            按次序执行下面两条指令:
            python3 manage.py makemigrations    # 数据表变化的记录
            python3 manage.py migrate           # 数据库同步命令(数据库的表就会发生变化)
    
    - 通过orm创建user表
        通过上面的四个步骤,就可以创建出user表
        新增表、删除表、新增字段、删除字段   --- 一个class就是一张表,删除=注释代码+执行两条命令,新增=新增字段代码+执行两条命令
            class User(models.Model):
                # 在这个类中,写入需要创建的字段
    
                # id字段,自增,int类型,是主键
                id = models.AutoField(primary_key=True)
    
                # name字段,varchar类型 ,长度32
                name = models.CharField(max_length=32)
    
                # pwd字段,varchar类型 ,长度32,可以为空
                pwd = models.CharField(max_length=32, null=True)
    
                # 增加字段
                xx = models.CharField(max_length=64)
    
                # # 再增加个字段
                # yy = models.CharField(max_length=64, null=True)
                #
                # # 再增加一个字段
                # zz = models.CharField(max_length=64, null=True, default='www')
                #
                # # 删除字段(只要注释掉 然后两条命令同步下就好了)
    
                方式一:
                在termimal中执行 python3 manage.py makemigrations
                                python3 manage.py migrate
                方式二:
                pycharm-tools-‘run manage.py Task..'-在命令输入框中输入migrations-在命令输入框中输入migrate
    
    
    
    
    
                1 单表的增删改查
                    # 为了验证测试方便,写了这个脚本 用来验证orm 数据增删改查
                    import os
                    if __name__ == '__main__':
                        os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ORM_Proj.settings')
                        import django
                        django.setup()
                        from app01 import models
    
                        (紧接着 上面的脚本写下去)
                        # 新增用户
                        # 方式一,通过对象来保存数据
                        # user = models.User(username=name, passwd=pwd)
                        # user.save()
                        # return HttpResponse('新增成功')
    
                        # 方式二 表模型 (常用方式)
                        # user = models.User.objects.create(username=name,passwd=pwd)
                        # print(user.username)
                        #
                        # return HttpResponse('create successful')
    
                        # 查询id=1的用户
                        # ret = models.User.objects.filter(id=1)       #结果是queryset对象,内部套了一个个的对象(理解为是一个列表)
                        # 查询名字为lich的数据
                        # ret = models.User.objects.filter(username='lich').first()  #结果是User对象,取出查询结果中的第一条数据
                        # ret = models.User.objects.filter(username='lich')
                        # print(ret)
    
                        # 删除的第一种方式: 把id=1的人删除(先查询后删除)
                        # ret = models.User.objects.filter(id=1).delete()   #把查询出来的所有结果删除
                        # print(ret)
    
                        # 删除的第二种方式:删除id=6的这个人(查询出对象,删除对象)
                        # ret = models.User.objects.filter(id=6).first()
                        # print(ret.username)
                        # print(ret.passwd)
                        # ret.delete()
    
                        # 修改数据的第一种方式: 修改id=5 的人的name为xxx
                        # ret = models.User.objects.filter(id=5).update(username = 'xxx') #所有查询出来的数据都更新
                        # print(ret)  #ret是影响的行数
    
                        # 修改数据的第二种方式:
                        user = models.User.objects.filter(id=5).first()
                        user.username = 'xxx'
                        # 没有user.update()
                        user.save()             #既可以保存 又可以更新
                        print(user.username)
    
                2 单表的其他操作
                    ### 单表的其他操作
    
                    # <1> all()返回queryset对象,查询表中所有记录
                    # ret = models.User.objects.all()     #把它当成queryset对象
                    # print(ret)
    
                    # <2> filter(**kwargs)返回queryset对象, 这种形式是'id=3 pwd=333' 是and条件
                    # ret = models.User.objects.filter(id=5,passwd='333')
                    # ret = models.User.objects.filter(id=5,passwd='123')   #和下面的一样一样的
                    # ret = models.User.objects.filter(**{'id':5,'passwd':'123'})
                    # print(ret)
    
    
                    # get(**kwargs)的返回值是User对象
                    # get查询的结果有且只有一个值才行,否则程序会报错
                    # user = models.User.objects.get(id=5)
                    # print(type(user))
    
                    # exclude(**kwargs)除了条件的记录以外的
                    # ret = models.User.objects.exclude(id=3)
                    # print(ret)
    
                    # order_by
                    # ret = models.User.objects.all().order_by('username')    # 查询出所有记录,升序排列
                    # ret = models.User.objects.all().order_by('-username')    # 查询出所有记录,降序排列
                    # print(ret.query)    #打印原生sql
                    # print(ret)
    
                    #reverse() 必须用在order_by之后
                    # ret = models.User.objects.all().order_by('passwd')
                    # ret = models.User.objects.all().order_by('passwd').reverse()
                    # print(ret)
    
                    # count()计算查询结果的总条目数
                    # ret = models.User.objects.all().count()
                    # ret = models.User.objects.filter(username='a').first()
                    # print(ret)
    
                    # exists()查询queryset对象的结果是否为空,返回的结果是true或false
                    # ret = models.User.objects.filter(id=10).exists()
                    # ret = models.User.objects.filter(id=8).exists()
                    # print(ret)
    
                    # values()  返回一个valueQueryset,运行后得到一个可迭代的字典序列
                    # ret = models.User.objects.all().values('username','passwd')
                    # print(ret)
                    # print(ret.first())
    
                    #values_list() 直接将取到的结果 组成一个元组
                    # ret = models.User.objects.all().values_list('username','passwd')
                    # print(ret)
    
                    # distinct 记录去重
                    # ret = models.User.objects.filter(username='lich')
                    # ret = models.User.objects.filter(username='lich').values('username').distinct()
                    # print(ret)
    
    
                    ### 模糊查询 使用__ 双下划线(基于__的模糊查询)
    
                    # in 查询id=1-7之中,的所有记录
                    # ret = models.User.objects.filter(id__in=[1,2,3,4,5,6,7])
                    # print(ret)
                    # print(ret.query)
    
                    # range between...and...
                    # ret = models.User.objects.filter(id__range=[1,7])
                    # print(ret)
                    # print(ret.query)
    
                    #  大于,小于,大于等于,小于等于
                    # ret = models.User.objects.filter(id__gt=9)   #大于
                    # ret = models.User.objects.filter(id__gte=9)   #大于等于
                    # ret = models.User.objects.filter(id__lt=7)   #小于
                    # ret = models.User.objects.filter(id__lte=7)   #小于等于
                    # print(ret)
    
                    # startswith 以xx开头
                    # ret = models.User.objects.filter(username__startswith='l')
                    # print(ret)
    
                    # contains  包含xx
                    ret = models.User.objects.filter(username__contains='i')    #严格大小写包含
                    ret = models.User.objects.filter(username__icontains='i')   #忽略大小写包含
                    print(ret)
    
    
                3 表操作(增删改)
                    - 一对一
                            # 一对一新增(注意所在database的字符集)
                            # 第一种方式:先新增author_detail
                            # author_detail = models.AuthorDetail.objects.create(addr='南京',phone='132111')
                            # author = models.Author.objects.create(name='lich',age=19,author_detail_id=author_detail.id)
    
                            # author_detail.pk 是主键
                            # author = models.Author.objects.create(name='lich',age=19,author_detail_id=author_detail.pk)
    
                            # 第二种方式:author_detail = 对象
                            # author_detail = models.AuthorDetail.objects.create(addr='东京',phone='142111')
                            # author = models.Author.objects.create(name='lqz',age=20,author_detail=author_detail)
    
                            # 修改
                            # 修改-第一种方式
                            # author = models.Author.objects.filter(pk=1).update(author_detail_id = 3)
    
                            # 修改-第二种方式
                            # author_detail = models.Author.objects.get(pk=3)
                            # author = models.Author.objects.filter(pk=1).update(author_detail = author_detail)
    
                    - 一对多
                            # 一对多的新增
                            # publish = models.Publish.objects.create(name='南京出版社',email='sddd',phone=3333,addr='南京')
                            # book = models.Book.objects.create(name='红楼梦',publish_date='2018-01-01',price=100.33,publish_id=publish.pk)
    
                    - 多对多
                            # 增加(给红楼梦这本书 添加两个作者:lich lqz)
                            # book = models.Book.objects.filter(name='红楼梦').first()
    
                            # 相当于拿到第三张表,add内可以传入对象,也可以传id
                            # book.authors.add(1,3)   #传id
    
                            # lich = models.Author.objects.get(pk=1)
                            # lqz = models.Author.objects.get(pk=3)
                            # book.authors.add(lich,lqz)  #传对象
    
                4 表操作(查)---基于对象的跨表查询:基于对象的查询其实是子查询(两次查询)
    
                        # 正向和反向
                        # 正向: 关联字段在当前表中,从当前表向外查,叫做正向
                        # 反向: 关联字段不在当前表中,从当前表向外查,叫做反向
    
                        # 一对一查询 ()
                        # 查询lich这个人的地址(正向查询按字段,反向查询表名小写)
                        # author = models.Author.objects.filter(name='lich').first()  # 先查找出这个对象
                        # print(author.author_detail) #需要在models类中,重写__str__(self)
    
                        # 查询地址为南京的作者人名(反向)
                        # author_detail = models.AuthorDetail.objects.filter(addr='南京').first()
                        # print(author_detail.author)
    
    
                        # 一对多(正向) 出版社和书 关联字段在书中
                        # 正向查询按字段,反向查询按 表名小写_set.all()
                        # 书~出版社:正向
                        # 查询红楼梦这本书的出版社地址
                        # book = models.Book.objects.filter(name='红楼梦').first()
                        # book.publish 就是出版社对象
                        # print(book.publish)
                        # print(book.publish.addr)
    
                        # 出版社~书:反向
                        # 查询南京出版社出版的所有书的名字
                        # publish = models.Publish.objects.filter(name='南京出版社').first()
                        # books = publish.book_set.all()
                        # print(books)
                        # for book in books:
                        #     print(book.name)
    
                        # 多对多,书和作者是多对多,关联字段authors在book中
                        # 总结:正向查询按字段.all() ,反向查询按 表明小写_set.all()
                        # 正向:book~author
                        # 查询红楼梦这本书的所有作者
                        # book = models.Book.objects.filter(name='红楼梦').first()
                        # authors = book.authors.all()
                        # print(authors)
                        # for author in authors:
                        #     print(author.name)
    
                        # 反向:author~book
                        # 查询作者是bbb的所有书
                        # author = models.Author.objects.filter(name='bbb').first()
                        # books = author.book_set.all()
                        # print(books)
                        # for book in books:
                        #     print(book.name)
    
                5 表操作(查)--- 基于双下划线的跨表查询(连表查询)
                        # 正向按 '基表关联字段__第二张表的字段',反向按 '基表表名小写__第二张表的字段'
    
                        # 一对一查询
                        # 查询lich这个人的地址(以author表作为基表)
                        # ret = models.Author.objects.filter(name='lich').values('name','author_detail__addr')
                        # print(ret)
    
                        # 查询lich这个人的地址(以author_detail表作为基表)
                        # ret = models.AuthorDetail.objects.filter(author__name='lich').values('addr','author__name')
                        # print(ret)
    
                        # 查询地址为上海的人的名字
                        # ret = models.Author.objects.filter(author_detail__addr='上海').values('name','author_detail__addr')
                        # print(ret)
    
                        # ret = models.AuthorDetail.objects.filter(addr='上海').values('author__name','addr')
                        # print(ret)
    
    
                        # 一对多查询
                        # 查询红楼梦这本书的出版社
                        # ret = models.Book.objects.filter(name='红楼梦').values('publish__addr')
                        # print(ret.first())
    
                        # ret = models.Publish.objects.filter(name='南京出版社').values('addr','book__name')
                        # print(ret)
    
                        # 查询南京出版社出版所有书的名字
                        # ret = models.Publish.objects.filter(name='南京出版社').values('book__name')
                        # print(ret)
    
                        # ret = models.Book.objects.filter(publish__name='南京出版社').values('name')
                        # print(ret)
    
                        # 多对多
                        # 查询红楼梦这本书的所有作者
                        # ret = models.Book.objects.filter(name='红楼梦').values('authors__name')
                        # print(ret)
    
                        # ret = models.Author.objects.filter(book__name='红楼梦').values('name')
                        # print(ret)
    
                        # 查询南京出版社出版过的所有书记的名字以及作者的姓名
                        # ret = models.Publish.objects.filter(name='南京出版社').values('book__name','book__authors__name')
                        # print(ret)
    
                6 表操作(查) --- 聚合查询
                        # 计算所有图书的平均价格
                        # from django.db.models import Count,Avg,Max,Min,Sum
                        # ret = models.Book.objects.all().aggregate(Avg('price')) #平均价格
                        # ret = models.Book.objects.all().aggregate(Max('price')) #最高价格...
                        # ret = models.Book.objects.all().aggregate(Count('price')) #书本数量
                        # ret = models.Book.objects.all().aggregate(Sum('price')) #书本数量
                        # print(ret)
                7 表操作(查)--- F/Q查询
                            # F取出表中字段对应的值
    
                            # 查询评论数大于阅读数的书
                            from django.db.models import F
                            from django.db.models import Q
    
                            # ret = models.Book.objects.filter(comment_num__gt=F('read_num'))
                            # ret = models.Book.objects.filter(comment_num__lt=F('read_num'))
                            # print(ret)
    
                            # 把所有书的评论数+1
                            # ret = models.Book.objects.all().update(comment_num = F('comment_num')+1)
    
                            # Q查询,构造出 与(&) 、 或(|) 、  非(~)的关系
                            # ret = models.Book.objects.filter(name='红楼梦',price=100)
                            # print(ret)
    
                            # ret = models.Book.objects.filter(Q(name='西游记')|Q(price='12.11'))   # 或 有点疑问
                            # ret = models.Book.objects.filter(Q(name='红楼梦')&Q(price=100)) #不如,并且关系来的简单  #与 有点问题
                            # ret = models.Book.objects.filter(~Q(name='西游记'))    # 非
                            # print(ret)
    
    
    
                    - 图书管理系统表
                        1 book表
                        2 publish表
                        3 author表
                        4 author_detail表
    
                        表关系
                            - author表和author_detail表是一对一的关系
                            - book表和publish表:一本书只能有一个出版社出版,一对多的关系一旦确立,关联字段写在多的一方
                            - book表和author表:多对多的关系,需要创建第三张表
                            **** 关联关系 ****:
                                一对一的关系,关联字段写在哪都行
                                一对多的关系,关联字段写在多的一方
                                多对多的关系,需要创建第三张表
                    重点:
                        1 author_detail = models.OneToOneField(to='AuthorDetail',to_field='id') #本质就是foregnkey+唯一性约束
                        2 publish = models.ForeignKey(to='Publish')     # ForeignKey对应的字段,同步到数据库,会自动加_id
                        3 authors = models.ManyToManyField(to='Author') # 自动创建第三张表
    模型层

    待补充...

    九、Forms---数据校验

    1 froms是什么?--- 校验数据
        - 数据校验
        - 渲染页面
        - 渲染错误信息
        - 局部和全局钩子函数
        - 使用css的样式

    如下代码来认识下forms的相关功能

    (***项目文件夹中新建static文件夹-将bootstrap文件粘贴过来***)

        # 如何使用forms组件
        # 第一步 写一个类集成forms
        from django import forms
        from django.shortcuts import HttpResponse
        from django.shortcuts import redirect
        from django.shortcuts import render
    
        from django.core.exceptions import ValidationError
        from django.forms import widgets
    
    
        class RegForms(forms.Form):
            # 第二步 写要校验的字段
            name = forms.CharField(min_length=3, max_length=8, label='用户名', error_messages={'min_length': '太短了',
                                                                                            'max_length': '太长了',
                                                                                            'required': '该字段必填'},
                                   widget=widgets.TextInput(attrs={'class': 'form-control'}))  # 变量名必须和register.html中的name保持一致
            pwd = forms.CharField(min_length=3, max_length=8, error_messages={'min_length': '太短了',
                                                                              'max_length': '太长了',
                                                                              'required': '该字段必填'},
                                  widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
            re_pwd = forms.CharField(min_length=3, max_length=8, label='确认密码', error_messages={'min_length': '太短了',
                                                                                               'max_length': '太长了',
                                                                                               'required': '该字段必填'},
                                     widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
            email = forms.EmailField(label='邮箱', error_messages={'invalid': '不是邮箱格式',
                                                                 'required': '该字段必填'},
                                     widget=widgets.EmailInput(attrs={'class': 'form-control'}))
    
            # 局部钩子函数(某个字段,自定义的规则,比如不能以sb开头,用户名已存在。。。等等)
            # 固定写法:方法名必须为clean_字段名
            # 要求:不能以sb开头
            def clean_name(self):
                # self是当前forms对象,cleaned_data是清洗后的数据,从字典中取出name
                name = self.cleaned_data.get('name')
                if name.startswith('sb'):
                    # 以sb开头了,禁止掉
                    raise ValidationError('不能以sb开头')
                else:
                    return name
    
            # 全局钩子函数(如:校验两次密码是否一致)
            # 固定写法:
            def clean(self):
                pwd = self.cleaned_data.get('pwd')
                re_pwd = self.cleaned_data.get('re_pwd')
                if pwd == re_pwd:
                    return self.cleaned_data
                else:
                    raise ValidationError('两次密码不一致')
    
    
        # 多传了要校验的字段,能正常通过校验,只不过多传的字段被清洗掉了
        # 少传了,不行
    
    
        def register(request):
            if request.method == 'GET':
                # 生成一个空的forms
                forms = RegForms()
                error = ''
                # return render(request, 'register.html',{'forms':forms})
            elif request.method == 'POST':
                # 第三步 生成一个Forms类的对象,传一个字典
                forms = RegForms(request.POST)
                # 第四步 调用forms的is_vaild方法,完成校验 is_valid返回true或者false
                if forms.is_valid():
                    # cleaned_data表示清洗后的数据,通过校验的字段数据以key:value形式形成一个字典
                    print(forms.cleaned_data)
                    return HttpResponse('注册成功')
    
                else:
                    print(forms.errors)
                    print(type(forms.errors))
                    print(forms.errors.as_data)  # 打印字典格式的错误信息
    
                    # 取全局错误信息
                    error = forms.errors.get('__all__')[0]
                    print(error)
    
            return render(request, 'register.html', {'forms': forms, 'error': error})
    views.py
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">
    
            {#    引入bootstrap#}
            <link rel="stylesheet" href="/static/bs-3.3.7/css/bootstrap.css">
            <title>我是注册页面</title>
            <style>
                .errors {
                    color: red;
                }
            </style>
    
    
        </head>
        <body>
    
        {#<form action="" method="post">#}
        {##}
        {#     不写csrf_toke 则会导致403forbidden#}
        {#    {% csrf_token %}#}
        {##}
        {#    <p>用户名: <input type="text" name="name"></p>#}
        {#    <p>密码: <input type="password" name="pwd"></p>#}
        {#    <p>确认密码: <input type="password" name="re_pwd"></p>#}
        {#    <p>邮箱: <input type="email" name="email"></p>#}
        {#    <p>xx: <input type="text" name="xx"></p>#}
        {##}
        {##}
        {#    <input type="submit" value="提交">#}
        {##}
        {#</form>#}
    
        {#<hr>#}
        {#<h1>forms渲染页面的第一种方式</h1>#}
        {#<form action="" method="post">#}
        {##}
        {#     不写csrf_toke 则会导致403forbidden#}
        {#    {% csrf_token %}#}
        {##}
        {#    <p>用户名: {{ forms.name }}</p>#}
        {#    <p>密码: {{ forms.pwd }}</p>#}
        {#    <p>确认密码: {{ forms.re_pwd }}</p>#}
        {#    <p>邮箱: {{ forms.email }}</p>#}
        {##}
        {##}
        {#    <input type="submit" value="提交">#}
        {##}
        {#</form>#}
    
    
        <div class="container-fluid">
            <div class="row">
                <div class="col-md-offset-3 col-md-6">
    
                    <hr>
                    <h1>forms渲染页面的第二种方式(###推荐使用###)</h1>
                    <form action="" method="post" novalidate>
    
                        {#     不写csrf_toke 则会导致403forbidden#}
                        {% csrf_token %}
                        {% for form in forms %}
    
                            {#        默认使用需要RegForms中的key值写入label#}
                            <p>{{ form.label }} : {{ form }} <span class="errors">{{ form.errors.0 }}</span></p>
    
                        {% endfor %}
    
    
                        <input type="submit" value="提交"> <span class="errors">{{ error }}</span>
                    </form>
    
                </div>
            </div>
        </div>
    
    
        {#<hr>#}
        {#<h1>forms渲染页面的第二种方式(###推荐使用###)</h1>#}
        {#<form action="" method="post" novalidate>#}
        {##}
        {#     不写csrf_toke 则会导致403forbidden#}
        {#    {% csrf_token %}#}
        {#    {% for form in forms %}#}
        {##}
        {#        默认使用需要RegForms中的key值写入label#}
        {#        <p>{{ form.label }} : {{ form }} <span class="errors">{{ form.errors.0 }}</span></p>#}
        {##}
        {#    {% endfor %}#}
        {##}
        {##}
        {#    <input type="submit" value="提交"> <span class="errors">{{ error }}</span>#}
        {#</form>#}
    
    
        {#<hr>#}
        {#<h1>forms渲染页面的第三种方式(###不推荐###)</h1>#}
        {#<form action="" method="post">#}
        {##}
        {#     不写csrf_toke 则会导致403forbidden#}
        {#    {% csrf_token %}#}
        {##}
        {#    {{ forms.as_p }}#}
        {#    {{ forms.as_ul }}#}
        {#    {{ forms.as_table }}#}
        {##}
        {#</form>#}
        {#<input type="submit" value="提交">#}
    
    
        </body>
        </html>
    register.html
        from django.conf.urls import url
        from django.contrib import admin
        from app01 import views
        urlpatterns = [
            url(r'^admin/', admin.site.urls),
            url(r'^register/', views.register),
        ]
    urls.py
        settings.py
        INSTALLED_APPS = [
        'app01.apps.App01Config',
        ]
    
        STATICFILES_DIRS = [
        os.path.join(BASE_DIR,'static')
        ]
    settings.py

    十、jdango框架内容总结

    0 HTTP协议
        -请求协议
            -请求首行:请求的方式,请求的地址
            -请求头:key:value的形式
            -请求体: 请求携带的数据(post)
        -响应协议
            -响应首行:状态码:1,2,3,4,5,
            -响应头:key:value的形式
            -响应体:响应的内容
        
    1 web框架的本质
        -socket服务端
    2 python中的web框架
        django
            -MTV
                -M:model
                -T:模板
                -V:视图层
            -MVC
                -M:model
                -V:模板
                -C:控制器,路由+视图
    
    3 路由
        1 url('正则表达式',函数内存地址,kwargs={默认参数},name=别名)  是一个函数
        2 分组(有名分组,无名分组)
        3 反向解析
            -在视图层生成:revers()
            -在模板层生成:{% url 'test' %}
        4 路由分发:include
        
        5 django2.0版的path
            re_path:1.x的url
            path:第一个参数是一个准确路径
        
    4 视图层
        -reuquest对象
            request.method
            request.path:liuqingzheng/p/9506212.html
            request.get_full_path():liuqingzheng/p/9506212.html?name=lqz&age=18
            request.GET:以get形式传的参数
            request.POST:以post形式传的参数
        -HttpResponse对象
            -三件套
                -render
                -redirect
                -HttpResponse
            -JsonResponse
        -上传文件:
            模板:enctype="multipart/form-data"
            视图:request.FILES.get('myfile')
    -模版层
        -模板语言:DTL:django 模板语言
        -{{ python的变量 }}    
        -深度查询  .
            -{{ 字典.name }}
            -{{ 列表.0 }}
            -{{ 对象.属性/方法(显示的是方法的返回值) }}
        -过滤器
            add
            date *****
            {{python的时间对象|date:'Y-m-d'}}
    -模型
      https://www.cnblogs.com/liuqingzheng/articles/9805991.html

    -django进阶
      组件:
        django与ajax
        分页器组件
        ****forms组件
        ****cookie与session组件
        中间件组件
        Auth模块:认证
        ContentType组件:表关联
        Go与python的区别:
          go没有异常处理:defer,panic,recover
          go没有class,通过结构体
  • 相关阅读:
    final修饰符
    数组知识点
    session的作用范围(转)
    c++之list学习
    C++之重载操作符
    C++之浅拷贝构造函数与深拷贝构造函数
    C++之友元
    C++之共有继承、保护继承、私有继承
    C++之类静态成员变量和静态成员函数
    C源程序到可执行文件的四个过程
  • 原文地址:https://www.cnblogs.com/lich1x/p/10577926.html
Copyright © 2020-2023  润新知