python_Django

1、Python用具 - pip
    1、作用:
        Python的软件包管理器,有一些python包被集成到了pip中。只要被集成到pip中的包,都允许通过pip直接安装
    2、安装 pip
        sudo apt install python-pip(python2)
        sudo apt install python3-pip(python3)
    3、使用pip/ pip3
        1、安装/下载/更新/删除 python包
            1、安装python包(下载并安装)
                sudo pip3 install SomePackage
                sudo pip3 install PyMySQL==0.7.11(如果不写版本号默认为最新的版本)
            2、下载python包(值下载不安装)
                sudo pip3 download SomePackage
            3、删除python包
                sudo pip3 uninstall SomePackage
            4、更新(升级)python包
                sudo pip3 upgrade SomePackage
        2、查看当前环境中所安装的包
            pip3 list
        3、搜索
            pip3 search SomePackage
        4、展示
            pip3 show SomePackage
        5、记录现有环境的python包
            1、pip3 freeze > requirements.txt
                将当前python环境中所安装的内容打包成一个txt文件
            2、pip3 install -r requirements.txt
                允许在当前系统下,逐一安装requirements.txt中所有列出的内容
2、Python工具 - VirtualEnv
    1、什么是VirtualEnv - 虚拟环境
        virtualEnv是python中的虚拟环境,在做python应用开发时,如果不想在大的python环境中安装各种各样的包的话,则可以虚拟出一个python环境,可以让虚拟环境专门为某一应用而存在。允许在虚拟环境中安装各种包且不影响大的python环境
    2、安装VirtualEnv
        sudo pip3 install virtualenv
    3、创建 和 使用 虚拟环境
        1、准备工作
            mkdir my_env
            cd my_env
        2、创建虚拟环境
            virtualenv 虚拟环境名称
            示例:virtualenv default
            创建指定版本的虚拟环境
            virtualenv -p /usr/bin.python2.7 名称
            virtualenv -p /usr/bin.python3.6 名称    
        3、启动虚拟环境
            注意:不能在bin目录中启动虚拟环境(根目录下的bin目录)
            source bin/activate
        4、退出虚拟环境
            deactivate
        5、删除虚拟环境
            rm 虚拟环境目录 -rf
        注意:在虚拟环境中使用pip安装和卸载内容时,不要使用sudo进行授权,如果使用则操作的是大环境
    4、虚拟环境管理工具 - VirtualenvWrapper
        1、作用
            第三方的管理工具,能够快速,高效且方便的管理虚拟环境
        2、安装虚拟环境管理工具
            sudo pip3 install virtualenvwrapper
        3、配置virtualenvwrapper
            在~(家目录)目录下,有一个终端管理文件 .bashrc(在~目录下,输入ll查看)
            配置.bashhrc,以便在启动终端时,就自动启动虚拟环境管理工具
            修改.bashrc: sudo vi .bashrc
            在.bashrc 最底部增加一下内容
            1、export WORKON_HOME=~/my_env:
                将~/my_env 作为虚拟环境的管理目录,所有使用virtualenvwrapper创建的虚拟环境都默认保存于此
            2、如果系统中包含多个python执行环境的话,则添加一下内容
                export VIRTUALENVWRPPER_PYTHON=/usr/bin/python3
            3、source /usr/local/bin/virtualenvwrapper.sh:默认启动刮管理工具
            4、在~目录下,执行一遍.bashrc
                source .bashrc
        4、使用虚拟环境管理工具
            1、创建并进入虚拟环境管理工具
                1、mkvirtualenv 虚拟环境名称
                2、mkvirtualenv --python=/usr/bin/python2.7 env2.7
            2、查看当前所维护的所有虚拟环境
                workon
            3、切换虚拟环境
                workon 虚拟环境名称
            4、退出虚拟环境
                deactivate
            5、删除虚拟环境
                rmvirtualenv 虚拟环境名称
3、WEB 与 服务器
    1、WEB:表示用户可以浏览的网页(HTML,CSS,JS)
    2、服务器:专门给用户提供服务的一台机器
        1、硬件 与 软件
            硬件范畴:一台主机
            软件范畴:一个能够接收用户请求并给出响应的程序

    1、APACHE

    2、TOMCAT

    3、IIS(Internet Information Service)

    4、Nginx

        2、作用:
            1、存储WEB上的信息(网页,图片,音视频,css,js)
            2、能够处理用户的请求(request)并给出响应(response)
            3、能够执行服务器端程序:如查询数据库
        3、WEB与服务器的关系

     WEB需要放在服务器上才能够被用户访问

            运行在服务器端的程序,可以由不同的语言来编写
                Java语言-->JSP
                C#语言-->ASP>NET
                PHP语言-->php
                Python语言-->Django
        4、网站请求的全过程
            1、用户:输入域名,通过域名解析(DNS)器得到IP地址
            2、向服务器发送http(开80端口)/https(开440端口)请求
            3、传输层TCP协议,经过网络传输和路由解析
            4、WEB服务器接收HTTP请求
            5、服务器处理请求内容,并进行必要的数据交换(我们需要做的事情)
            6、将响应的内容发回给浏览器(响应)
            7、浏览器解析HTML
            8、显示解析好的内容

4、框架
    1、什么是框架
        框架是一个为了解决某些开放性问题而存在的一种结构。框架本身提供了最基本的功能,我们只需在这些基本功能上构建自己的操作即可。
    2、框架的优点
        1、快速开发 - 基本功能已经提供好了
        2、可以解决大部分问题
        3、bug少,稳定性较高
    3、框架的分类
        1、前端框架
            处理前端内容(HTML,CSS,JS)
        2、后端框架
            处理服务器程序的
            Spring -Java
        3、全栈框架
            包含WEB整体的解决方案,包括开发框架,运行环境
            Rails(Ruby)
            Django(Python)
        4、Python的WEB框架
            1、Django:重量级的Python Web框架
            2、Tornado:异步框架
            3、Flask:轻量级框架,直接引入模块即可使用
            4、Webpy:轻量级框架
            5、Web2py:全栈框架,webpy的加强版

1、设计模式 与 框架模式
    1、设计模式
        设计模式,是一套被反复使用,多数人知晓并经过分类的代码设计经验的总结,是为了解决一些通用性问题的
        目的:重用代码并保证代码的可靠性
        官方认证的设计模式有23中:单列模式,抽象工厂模式,观察者模式等 《大话设计模式》
    2、框架模式
        代码的重用,框架模式是解决如何设计程序框架的代码,在框架模式中会包含多种的设计模式
        如:MVC,MTV,MVVM,ORM,...
        1、MVC
            M:Models,模型层,
                在程序中主要处理数据,负责在数据库中对数据进行存取操作(CRUD)
            V:Views,视图层
                应用程序中处理显示的部分内容(HTMl,JSP)
            C:Controllers,控制器层
                处理用户交互的部分,通常负责从模型中取出数据,再进行业务的处理,最后将数据给视图,并将视图给客户端

        2、MTV
            M:Models 模型层,

     模型层,负责数据库建模以及CRUD的操作
            T:Templates 模板层
                用于处理用户显示的部分内容,如:html
            V:Views 视图层
                处理用户交互部分,从模型中获取数据,再将数据给模板,在显示给用户

2、Django框架
    1、什么是Django
        是一个开源框架,2005年发布,采用python语言开发的。早期Django是做新闻和内容管理的网站的,提供了非常强大的后台管理系统,采用的是MTV框架模式
    2、Django的优缺点
        1、优点
            1、开源框架,有完美的文档支持
            2、解决方案比较完整,内部功能也比较多
            3、提供完整的路由系统,优雅的URL解析方式
            4、自助式的后台管理
        2、缺点
            1、耦合度偏高
    3、Django的安装
        1、Linux中的安装
            1、查看已安装的Django
                1、进入到虚拟环境中
                2、进入到python的交互模式中
                3、在交互模式中输入
                    1、import django
                    2、django.VERSION
            2、在线安装 - 使用 pip
                1、终端中输入
                    pip install django(安装django的最高版本)
                    pip install django==1.11.8
                    注意:在虚拟环境中不要使用sudo
            2、离线安装
                1、下载所需要的django包
                2、在Linux中解压django
                    tar  - xvf Django-1.11.8.tar.gz
                 3、进入到Django文件夹中
                 4、安装
                     python setup.py install
        2、Windows中的安装
            1、在线安装
                控制台: pip3 install django==1.11.8
            2、离线安装
                1、下载django安装包
                2、解压django包
                3、进入到django包中
                    python setup.py install
    4、使用Django
        1、创建Django项目
            直接使用django-admin去创建Django项目
            1、找到项目文件夹(自定义)
            2、使用django-admin 指令
                django-admin startproject 项目名称
        2、启动Django项目
            1、进入到项目文件夹中
            2、通过manage.py 启动项目
                1、
                    python manage.py runserver
                    或 ./manage.py runserver
                    只能在本机访问
                    http://localhost:8000
                    http://127.0.0.1:8000
                2、
                    python manage.py runserver 0.0.0.0:8000
                    或 ./manage.py runserver 0.0.0.0:8000
                    允许在局域网内访问。可以通过IP地址访问,但是需要将setting.py文件中ALLOWED_HOSTS = []修改为ALLOWED_HOSTS = ["*"]
    5、Django结构介绍
        1、manage.py
            负责执行django中的各项操作的文件,又叫命令脚本文件
            如:
                1、启动服务
                2、创建应用
                3、创建管理员、用户
                ....
        2、主文件夹(名称与项目名称相同)
            存放项目的最基础的配置文件
            1、__init__.py
                项目初始化文件,每当服务器启动的时候,会自动执行,如果有自定义的初始化操作,需要放在该文件中
            2、urls.py
                项目的基础url(路由)配置文件
                路由:去哪里找执行的程序
            3、wsgi.py
                配置应用服务器的文件,暂时不用
            4、settings.py(重要)
                项目的主设置文件:应用:模板,数据库,语言,时区....
                1、BASE_DIR:项目的绝对路径
                2、DEBUG:调试模式
                    开发过程中,推荐使用Ture,上线运行时,必须改为False
                3、ALLOWED_HOSTS
                    设置允许访问本地项目的地址列表,如果不设置的话,只能本机访问,推荐用"*",表示任何机器都允许访问当前项目
                4、INSTALLED_APPS
                    指定已经安装的应用,如果有自定义应用的话,需要在此注册
                5、MIDDLEWARE:注册中间件
                6、ROOT_URLCONF:指定项目的基础路由配置文件
                7、TEMPLATES:指定模板的信息
                8、DATABASES:指定数据库的信息
                9、LANGUAGE_CODE:指定语言,允许修改为zh-Hans
                10、TIME_ZONE = 'UTC':指定时区,建议改为Asia/Shanghai
    6、settings的加载流程
        1、先加载globals_settings.py
            位于:/home/xdl/my_env/env3.5/lib/python3.6/site-packages/django/conf/globals_settings.py
        2、再加载项目中的settings.py
            注意:如果globals_settings中的内容与项目settings中的内容冲突的话,优先使用项目中的settings中的内容
    7、初始 django-admin 和 mangage.py
        1、在终端输入django-admin命令
            check
            compilemessages
            createcachetable
            dbshell
            diffsettings
            dumpdata
            flush
            inspectdb
            loaddata
            makemessages
            makemigrations
            migrate
            runserver
            sendtestemail
            shell:python3 manage.py shell ,进入django的交互环境,
            showmigrations
            sqlflush
            sqlmigrate
            sqlsequencereset
            squashmigrations
            startapp
            startproject#创建项目
            test
            testserver
        2、进入项目主目录文件夹,输入./manage.py
            [auth]
                changepassword #修改密码
                createsuperuser #创建超级用户
                示例:
                    1、首先需要创建一张用于存储用户信息:./manage.py migrate
                    2、创建用户:./manage.py createsuperuser
            [contenttypes]
                remove_stale_contenttypes

            [django]
                check
                compilemessages
                createcachetable
                dbshell            #进入到Django数据shell交互模式
                diffsettings
                dumpdata
                flush
                inspectdb    #将数据表直接导出为Models
                loaddata
                makemessages
                makemigrations#创建数据库日志文件,记录Models的改动
                migrate            #将数据库日志文件同步到数据库中
                sendtestemail
                shell
                showmigrations
                sqlflush
                sqlmigrate
                sqlsequencereset
                squashmigrations
                startapp        #创建应用
                startproject
                test
                testserver

            [sessions]
                clearsessions

            [staticfiles]
                collectstatic
                findstatic
                runserver    #启动服务
    8、URL的使用
        1、urls.py
            默认在主文件夹中,包含所有的地址映射。
            每当一个请求产生后,都会到urls.py中进行地址的匹配,匹配上后再找对应的处理程序(View视图)去处理
        2、测试
            1、在主文件夹中,创建views.py
                作用:包含所有定义好的视图(处理程序)
                内容包括:
                    from django.http import HttpResponse
                    def fun_views(request):
                        '''视图,处理用户的请求并给出响应
                            request:表示用户的请求信息
                            HttpResponse:响应给客户端的内容'''
                        return HttpResponse("Hello django")
            2、在urls.py中追加
                from .views import *
                urlpatterns = [
                    url(r'^admin/',admin.site.urls),
                    //如果访问路径是fun/ 的话,则交给fun_views视图处理函数去处理
                    url(r'^fun/$',fun_views),//如果这里添加了自定义视图处理函数时,localhost:8000将会失效
                    //如果请求的URL在这里可以匹配多个,则只能执行第一个匹配到的
                ]
        3、url函数
            url函数的语法:
            url(regex,views,kwargs=None,name=None)
                1、regex:正则表达式,匹配请求的url
                2、views:url处理的视图函数,通常都是自定义的
                3、kwargs:字典,用来向views传参
                4、name:字符串,给url()起一个别名,主要在模板中匹配{%url%}一起使用
        4、url向view传参
            1、使用正则表达式传参
                使用正则表达式的子组传参,使用()
                urlpatterns=[
                    //访问路径必须是fun
                    url(r'^fun/$',fun_views),
                    //访问路径必须是fun
                    url(r'^fun/$',fun_views),
                    url(r'^fun/(\d+)',fun_arg1_views),
                ]
                注意
                    1、在url()中,一个子组()表示一个参数
                    2、在views.py中,对应的处理函数要根据url()中子组的个数,相应的定义参数,定义的参数要位于request之后
                练习:
                    1、访问地址:localhost:8000/18/0223/15,如何获取18 0223 15
                        def fun_arg3_views(request,num1,num2,num3):
                            return HttpResponse("%s %s %s"%(num1,num2,num3));
                        url(r'^(\d{2})/(\d{4})/(\d{2})$',fun_arg3_views),
            2、使用url()第三个参数,字典传参
                urlpatterns=[
                    url(r'^showname/$',show_views,{'name':"zhang",'age':25}),
                ]
                views.py:
                def show_views(request,name,age):
                    return HttpResponse(name+':'+str(age))
                注意:
                    1、视图处理函数中,必须声明参数
                    2、参数的名称 和 位置 必须要与字典中的名称和位置保持一致    

3、Django中的应用
    1、什么是应用
        应用是网站中的一个独立的模块,包含独立的显示信息
        在项目主文件夹中一般不处理其他的请求,主要就做初始化设置 以及 地址的分发
        实际操作中,会将请求交给不同的应用去处理

    2、创建应用
        1、命令: ./manage.py startapp 应用名称
        2、在settings.py中注册应用:
            INSTALLED_APPS = [
                'django.contrib.admin',
                'django.contrib.auth',
                'django.contrib.contenttypes',
                'django.contrib.sessions',
                'django.contrib.messages',
                'django.contrib.staticfiles',

                'index',
            ]
    3、应用的结构组成
        1、migrations 目录
            存放数据库日志文件,是一个django与数据库交互的中间文件
        2、__init__.py
            应用的初始化操作文件
        3、admin.py
            应用的后台管理配置文件
        4、apps.py
            应用的属性设置文件,不需改动
        5、modles.py
            Modles模型文件
        6、tests.py
            测试模块,通常不用
        7、views.py
            定义视图的py文件
        练习:
            创建应用,并进行注册
            在day02_exer 中创建应用
            1、index - 主页面的应用
                ./manage.py startapp index
            2、news - 新闻的应用
                ./manage.py startapp news
            3、sports - 体育的应用
                ./manage.py startapp sports
            4、musics - 音乐的应用
                ./manage.py startapp musics
                在settings.py中的INSTALLED_APPS列表中添加以上应用
                INSTALLED_APPS = [
                    'django.contrib.admin',
                    'django.contrib.auth',
                    'django.contrib.contenttypes',
                    'django.contrib.sessions',
                    'django.contrib.messages',
                    'django.contrib.staticfiles',

                    'index',
                    'news',
                    'sports',
                    'musics',
                ]

from django.conf.urls import url,include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
]
urlpatterns += [
    url(r'^music/', include('music.urls')),
    url(r'^sport/',include('sport.urls')),
    url(r'^news/',include('news.urls')),
    #匹配空的时候一定要放在最后
    url(r'^', include('index.urls')),
]

1、Django模板(Template)
    1、什么是模板
        就是一个网页,可以被view响应给用户
        目的是为了解决复杂的显示问题
    2、模板的设置
        1、BACKEND:指定模板的搜索引擎,不用改动(就是指定到哪里搜索模板)
        2、DIRS:指定模板所存放的目录,如果DIRS为空的话并且APP_DIRS为True,那么django会自动搜索每个应用中的templates文件作为模板管理目录
            DIRS = ['index.trmp','music.temp']
            推荐:
                1、DIRS保持为空
                2、在每个应用中,创建一个templates的文件夹
        3、APP_DIRS:值为boolean类型
            True:首先从DIRS中指定的文件夹中查找模板,如果没有找到指定模板的话,则再搜索templates目录
    3、模板的加载方式
        1、使用loader 获取模板,通过HttpResponse进行响应
            from django.template import loader
            def xxx(request):

     #1、通过loader加载模板
                t = loader.get_template('show.html')

     #2、将模板渲染成字符串
                html = t.render({})

     #3、通过HttpResponse响应回去
                return HttpResponse(html)
            说明:
                render({}),字典中的是数据,会传入html文档中,在HTML中通过{{字典的键}}取值,{{num1}}
                render({}),字典参数,可以通过locals(),获取该函数中的局部变量的字典,进行传递
        2、使用render直接加载
            return render(request,'模板名称',{})
    4、url()的name参数
        urlpatterns = [
            url(regex,views,kwargs=None,name=None)
        ]
        name:定义当前url的别名,允许在Template中使用该别名来找到对应的url(反向解析)

  反向解析:通过name 的值来匹配出对应的regex路径
    在Django模板中使用name实现连接
          {% url 'name值' %}
          如果url中有参数需要{% url 'name值' 参数1 参数2 ...%}

  在视图中实现name别名反向解析出对应的URL地址

    需要引包:from django.shortcuts import reverse

    语法:

      1、无参数解析:reverse("别名")

      2、带参数解析:reverse("别名",args = (参数1,参数2....))

from django.shortcuts import render
from django.http import HttpResponse
from django.urls import reverse
# Create your views here.
def index_views(request):
    return HttpResponse("news index_views")

def reverse_views(rquest):
    #反向解析url(不带参数),/news/reverse
    #url = reverse("reverse")
    #反向解析url(带参数),/news/reverse/2018/08
    url = reverse('reverse_args',args=(2018,'08'))
    return HttpResponse("反向解析出的URL:"+url)

    5、模板的语法
        1、变量
           1、 作用:允许将后端的数据传递给模板(html),在模板中,会根据变量的实际值进行显示
           2、在Django中允许传递给模板作为变量的数据类型
                   数字,字符串,列表,元组,字典,函数,对象,类。 集合不可以

   3、变量语法
              变量们必须要封装到字典中才能传递给模板
                1、使用render加载模板 
                    dic = {
                        ’变量1’:‘值1’,
                        ‘变量2’:‘值2’,
                        ....
                    }
                    return render(request,'xx/html',dic)
                2、使用loader加载模板
                    dic = {
                        ’变量1’:‘值1’,
                        ‘变量2’:‘值2’,
                        ....
                    }
                    t = loader.get_template('x.html')

       #渲染成字符串是需要传递变量字典到模板中
                    html = t.render(dic)
                    return HttpResponse(html)
            4、在模板中使用变量:
                  {{变量名}}
                如果要取列表,字典,元组中的值要通过变量名.下标 或 变量名.键

def var_views(request):
    #声明变量字典
    l = ['金毛狮王','白眉鹰王','']
    t = ('潘林连','西门庆','武大郎')
    dic = {
        'SHZ':"水浒传",
        'xyj':"西游记",
        'hlm':'红楼梦'
    }
    def fun():
        return '函数'
    class Dog(object):
        name = '阿拉斯基'
        def eat(self):
            return '吃狗粮'
    vars = {
        'num':15,
        'str':'模板中的字符串变量',
        'tup':t,
        'list':l,
        'dic':dic,
        'fun':fun(),#等价于'fun':fun
        'dog':Dog(),#等价于Dog

    }
    return render(request,'02_var.html',vars)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h3>num:{{ num }}</h3>
    <h3>str:{{ str }}</h3>
    <h3>tup:{{ tup }}</h3>
    <h3>tup[0]:{{ tup.0 }}</h3>
    <h3>list:{{ list }}</h3>
    <h3>list[1]:{{ list.1 }}</h3>
    <h3>dic:{{ dic }}</h3>
    <h3>dic['xyj']:{{ dic.xyj }}</h3>
    <h3>fun:{{ fun }}</h3>
    <h3>dog:{{ dog }}</h3>
    <h3>dog.name:{{ dog.name }}</h3>
    <!--调用类方法内中函数时只用对象.函数名,无需加括号-->
    <h3>dog.eat:{{ dog.eat }}</h3>
***********************************************************
    <h3>tup:{{ t }}</h3>
    <h3>tup[0]:{{ t.1 }}</h3>
    <h3>list:{{ l }}</h3>
    <h3>list[1]:{{ l.1 }}</h3>
    <h3>dic:{{ dic }}</h3>
    <h3>dic['xyj']:{{ dic.xyj }}</h3>
    <h3>fun:{{ fun }}</h3>
    <h3>dog:{{ Dog }}</h3>
    <h3>dog.name:{{ Dog.name }}</h3>
    <!--调用类方法内中函数时只用对象.函数名,无需加括号-->
    <h3>dog.eat:{{ Dog.eat }}</h3>
</body>
</html>

        2、标签
            1、什么是标签
                允许嵌套一些服务器端的逻辑运算到模板中
            2、语法
                {% %}
            3、常用标签
                1、{% if 条件 %} ...{% endif %}
                    接受:not and or
                    但是 :and 和 or 不能同时出现
                    以下内容当成False处理:
                        空[]
                        空()
                        空{}
                        数字:0
                        空字符串
                        特殊对象:None
                2、{%if 条件 %}...{%else%}...{%endif%}
                3、
                    {%ifequal 值1 值2%}...{%endifequal%}:判断值1与值2是否相等
                    {%ifequal 值1 值2%}...{%else%}...{%endifequal%}
                4、{% for 变量 in 列表|元组|字典%}{%endfor%}
                    允许使用的内置变量(免声明)
                    forloop
                    1、forloop.counter:记录循环的次数
                    2、forloop.counter0:同上,但从0开始
                    3、forloop.revcounter:记录未被遍历的数量
                    4、forloop.revcounter0:同上,从0开始
                    5、forloop.first:布尔值,标记是否为第一个项目
                    6、forloop.last:布尔值,表示是否为最后一个项目

 {% for str in l %}
        <!--将第一条数据的背景色变为红色-->
         <h3 {% if forloop.first %}
             style="background:red;"
         {% endif %}
         >数据{{forloop.counter0}}:{{ str }}
         </h3>
    {% endfor %}

                5、{%url%}
                6、{%static%}
                7、{%extends%}:用作模板继承

     8、comment 标签

      作用:在服务器端就被注释的内容,不会被渲染到客户端的

      <!--注释内容-->>:客户端注释会被渲染到客户端,在其中的{{ 服务器代码}},回去执行解释
        3、过滤器
            1、作用
                在显示变量之前,允许对数据进行筛选或改变
            2、过滤器的语法
                {{var|过滤器}}
            3、常用过滤器
                1、{{var|upper}}:将var的数据变为大写
                2、{{var|lower}}:将var的数据变为小写
                3、{{var|add}}:
                4、{{var|floatformat:n}}:将var四舍五入到n为小数
                5、{{value|truncatechars:n}}:将value截取保留至n位字符(包含三个点...)

  自定义标签和过滤器

     步骤:
            1、在应用目录下创建templatetags目录
            2、在templatetags创建模块文件,并导入Django内部方法
          3、在模板最上方中加载自定义的模块文件,{% load 模块文件名%}

     自定义过滤器

        1、在templatetags目录下创建python模块,例如命名为tags.py

from django import template
register = template.Library()
@register.filter
def value_verification(value): # value为前端传递的参数
  '''最多传递两个参数'''
     try:
          int(value)
          return True
     except:
          return False
<!--前端模块中的代码-->
{% load app01_func %} {% if load|value_verification %}   {{ num }} is a valid int number. {% else %}   {{ num }} is letter. {% endif %}

      自定义标签

        1、simple_tag的代码方式与filter一样,不同的是在装饰器部分和前端调用的方式不同

from django import template
register = template.Library()
@register.simple_tag
def value_verification(value): # value为前端传递的参数
    '''可以传递多个参数'''
     try:
          int(value)
          return True
     except:
          return False

        2、前端模块中调用{% value_verification  num %}

     filter 和 simple_tag的区别

        1、filter可以用在if 条件判断中,但是最多只能有两个参数,可以将多个参数用特定字符拼接成一个字符串传递给后端,后端通过拆分获取多个参数

        2、simple_tag不能用在if、for语句中,可以传递多个参数

        3、模板中的调用方式不同

          1、filter将我们指定的函数变成了返回值可执行的方法{{ 参数1 | value_verification:参数2 }},冒号后面不能有空格

          2、simple_tag将函数功能变为标签功能{% value_verification  参数1 参数2...... as 返回结果的别名 %}
        4、静态文件的处理
            1、什么是静态文件

      在Django中,不被解释器动态解析的文件就称为静态文件,在Django中,物理路径(磁盘中真是存在的)是无法找到静态文件的
                模板中所用到的css,js,image等一些资源文件都是静态文件
            2、Django中静态文件的处理
                需要在settings.py中设置静态文件的访问路径 和 存储路径
                1、STATIC_URL:设置静态文件的访问路径
                    STATIC_URL = '/static/'
                2、STATICFILES_DIRS:设置静态文件的存储路径
                    1、STATICFILES_DIRS = (BASE_DIR,'static')

       2、STATICFILES_DIRS = (os.path.join(BASE_DIR,'静态文件目录名'))

       静态文件目录存放位置:

        1、所有应用中创建一个同名目录

        2、项目的根目录处也可以创建一个同名文件
                3、访问静态资源
                    1、<img src="/static/images/huiyuan.jpg">
                    2、使用{%static%}访问静态资源

       {%static%}:表示的就是静态文件资源的访问路径(就是setting.py中STATIC_URL的值,STATIC_URL = '/static/')
                        1、模板的最顶层增加{%load static%}
                        2、使用静态资源文件时
                            <img src="{%static 'images/huiyuan.jpg'%}"

        5、模板的继承
            1、什么是模板的继承
                当多个模板(网页)具备大部分相同的内容时,就可以使用继承的方式,将相同的内容继承过来,在增加/修改属于自己的内容即可
            2、模板继承的语法
                1、在父模板中增加{%block 名称%}...{%endblock%}
                    说明:名称不能重复
                2、在子模板中
                    1、在最顶层第一句话增加:
                        {%extends '父模板的名称'%}
                    2、增加block标记,编写属于自己的内容
                        {%block 名称%}//这里的名称要与父模板{%block 名称%}中的名称相同
                            属于子模板中自己的内容
                            //一旦引用次标记,则此处不再显示父模块中的内容
                        {%endblock%}

2、Django模型(Model)
    1、什么是模型
        模型,就是根据数据中数据表的结构而创建出来的class。
        数据库中的每一张表到编程语言中就是一个class
        数据库表中的每一个字段(列)可以被构建成class中的一个成员变量(属性),并且在模型中,完成对数据库的CRUD操作
            C:Create
            R:Retrieve(检索查找)
            U:Update
            D:Delete
    2、创建 和 使用模型 - ORM
        1、什么是ORM
            ORM:Object Relational Mapping(对象关系映射)
            简称:ORM, O/RM, O/R Mapping
            三大特征:
                1、数据表到类(class)的映射

       允许将表自动生成一个类,也允许将一个类自动生成一张表
                2、数据类型的映射
                    允许将表中字段的类型自动生成到编程语言中对应的数据类型,也允许将编程语言中的数据类型生成数据表中对应的字段类型
                3、关系映射
                    数据库中表的关联关系:
                        一对一,一对多(多对一),多对多
                    将表中的关联关系也映射到编程语言的class中,通过创建对象的关系来完成映射

       允许将类与类之间的关系自动映射成表与表之间的关系

      class A(object):

        name = None

      class B(object):

        a = A()#在表中通过外键进行关联

        2、ORM的优点
            1、提高了开发效率,能够自动完成实体类到数据表的映射,

    2、可以省略庞大的数据访问层,即便不用SQL编码(语句),就能够完成对数据的CRUD操作
        3、创建 和 配置数据库
            1、创建数据库(支持中文)
                create database webdb default charset=utf8

      create database webdb default charset  utf8 collate utf8_general_ci
            2、Django中数据库的配置
                settings.py中配置数据库信息
                DATABASES = {
                    'default': {
                        'ENGINE': 'django.db.backends.mysql',
                        'NAME': 'webdb',
                        'USER': 'debian-sys-maint',
                        'PASSWORD':'Lo0r79JmxvMFNtA2',
                        'HOST':'localhost',
                        'PORT':'3306',
                    }
                }
                1、ENGINE:引擎
                    django.db.backends.mysql
                2、NAME:要连接到的数据库名称
                3、USER:用户名称
                4、PASSWORD:密码
                5、HOST:连接的主机,本机的话localhost/127.0.0.1/不写
                6、PORT:端口,3306
            4、安装pymysql

      注意:Django中要连接MySQL数据库的话要依赖于MySQLdb,通过pymysql解决问题
                pip install pymysql==0.7.11
            5、在主文件夹找找到__init__.py写入

                import pymysql
                pymysql.install_as_MySQLdb()#转换为MySQLdb 
            6、启动django
                ./manage.py runserver
        4、数据库的同步操作
            1、./manage.py makemigrations
                作用:将每个应用下的models.py文件生成一个数据库的中间文件(映射成一个数据库日志文件),并存放在migrations目录中
            2、./manage.py migrate
                作用:将每个应用下的migrations目录中的中间文件(日志文件)同步到数据库中

    当migrations目录中没有中间文件时,会创建Django中自带的数据表

    

        5、编写Models(重难点)
            1、注意:
                1、Models中的每个class都称之为 模型类(Model)或实体类(Entry)
                    实体:数据表中的一行记录,就是一个实体
                    实体完整性:确保每张表中的数据不能有重复的,数据表中的主键,是实现实体完整型的方式之一
                2、Models中的每个实体类,必须继承自models.Model
            2、示例:
                在models.py中
                from django.db import models
                class Publisher(models.Model):
                    name = models.CharField(max_length=30)
                    address = models.CharField(max_length=50)
                    city = models.CharField(max_length=20)
                    website = models.URLField()

from django.db import models
import datetime

# Create your models here.
#实体类:Publisher
#对应到数据库中的一张,表表名为index_publisher(应用名_实体类名小写)
#该类中的每个属性,会对应到数据表中的每个字段啊
class Publisher(models.Model):
    name = models.CharField(max_length=30,deafult='匿名')
    address = models.CharField(max_length=60)
    city = models.CharField(max_length=30)
    country = models.CharField(max_length=30)
    website = models.URLField()

class Author(models.Model):
    name = models.CharField(max_length=30)
    age = models.IntegerField()
    email = models.EmailField(null=True)

class Book(models.Model):
    title = models.CharField(max_length=50)
    publication_date = models.DateField(default=datetime.datetime.now())

        6、Django中的字段类型以及字段选项
            1、字段类型(Field Types):映射到数据库表中的数据类型
                1、BooleanField():tinyint()
                2、CharField():varchar()
                3、DateField():date
                4、DateTimeField():datetime(6),6位精度 2018-08-27 16:43:20.000000 
                5、FloatField():double()
                6、FileField():varchar(100)
                7、EmailField():varchar(254)
                8、IntegerField():int(11)
                9、ImageField(upload_to=None):varchar(100)存放文件路径

      uimg=models.ImageField(upload_to='images/users/')

                10、URLField():varchar(200)
                11、DecimalField(max_digits=7,decimal_places=2):decimal(7,2),通常用来表示钱

     12、TextField():longtext()存放大量数据
            2、字段选项:对生成的字段的说明信息
                1、null:是否允许为空,默认为False
                    name = models.CharField(max_length=30,null=True)
                2、default:为该字段设置默认值
                    name = models.CharField(max_length==30,default="匿名")

     3、db_cloumn

      指定当前属性(字段)对应到数据库表的列名,如果不指定则采用属性名作为列名

    3、说明:

      如果在原先实体类中添加属性(字段)时,必须给这个字段设置为允许为空(null=True)或者给一个默认值default=‘值’,否则会有如下提示     

       1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
       2) Quit, and let me add a default in models.py

        7、数据的导入和导出(数据迁移)以及版本切换
            1、版本切换
                ./manage.py migrate 应用名称 版本号
                ./mansge.py migrete index 0001  //会将原先已经映射的数据表删除
            2、数据库的导出
                1、mysqldump -u... -p 数据库名 >文件.sql
                    导出所有的表结构以及数据
                2、mysqldump -u... -p -d 数据库名 >文件.sql
                    只导出所有的结构
            3、数据库的导入
                mysql -u.. -p 数据库名 < 文件.sql
            4、通过数据库自动导出Models
                ./manage.py inspectdb >文件名.py
                表名index_book变为实体类名为IndexBook
                class IndexBook(models.Model):
                    title = models.CharField(max_length=50)
                    publication_date = models.DateField()

                    class Meta:
                        managed = False
                        db_table = 'index_book'

1、模型的数据库操作方法(CRUD)
    1、通过视图向DB中增加数据
        1、Entry.objects.create(属性=值,属性=值)

    返回值:创建好的实体,
            Author.objects.create(name='王宝强',age=33,email='wangbaoqiang@green.com')
        2、创建一个实体对象,并通过save()方法完成增加
            obj = Entry(属性=值,属性=值)
            obj.save()
        3、通过字典创建实体对象,在调用save()
            dic = {
                "name":"xx",
                "age": ,
                "email":"xx"
            }
            obj = Author(**dic)
            obj.save()
            示例:    
            dic = {"name":"陈羽凡","age":38,"email":"chenyufan@green.com"}
            obj = Author(**dic)
            obj.save()

def add_views(request):
    #方法1、向Author实体中增加一条记录
    ret = Author.objects.create(name='老舍',age=85,email='laoshe@163.com')
    return  HttpResponse(ret)#返回一个实体类对象,age是str,int都可以
    #方法二
    author = Author(name='巴金',age=75,email='bajin@163.com')
    ret = author.save()
    return HttpResponse(ret)#返回值为None
    #方法三
    dict = {
        'name':'冰心',
        'age':80,
        'email':'bingxin@163.com',
    }
    author = Author(**dict)
    ret = author.save()
    return HttpResponse(ret)#返回None

2、查询操作(重难点)
    所有的查询都要在Entry.objects.基础上完成
    1、基本查询操作    
        语法:all()
        用法:Entry.objecsts.all()
        返回:QuerySet(查询结果集,是一个封装了若干对象的列表)
            <QuerySet [<Author: Author object>, <Author: Author object>, <Author: Author object>]>

    <QuerySet [<Author: 老舍>, <Author: 老舍>, <Author: 巴金>, <Author: 冰心>]>

def query_views(request):
    #查询Author实体中所有的数据
    #返回一个列表,其中封装了若干的对象
    authors = Author.objects.all()
    for au in authors:
        print(au.name,au.age,au.email)
    return HttpResponse('query ok')

    2、查询接口
        1、all()
            Entry.objects.all()
            相当于:select * from ...
        2、查询指定列的操作

     语法:values("列名1",‘列名2’...)
            Entry.objects.values('name')
            相当于:select name from ...
            作用:查询所有记录的某一列的值
            返回值:QuerySet(查询结果集,是一个封装了若干字典的列表)<QuerySet [{'name': '王宝强'}, {'name': '贾乃亮'}, {'name': '陈羽凡'}]>

    注意:values()可以用在QuerySet(查询结果集)后面比如:all().values()

def query_views(request):
    #查询Author实体中name 和 age的信息
    authors = Author.objects.values('name','age')
    print(authors)
    # < QuerySet[
    #       {'age': 85, 'name': '老舍'},
    #       {'age': 85, 'name': '老舍'},
    #       {'age': 75, 'name': '巴金'},
    #       {'age': 80, 'name': '冰心'}] >
    for au in authors:
        print(au['name'],au['age'])
        # 老舍 85
        # 老舍 85
        # 巴金 75
        # 冰心 80
    return HttpResponse('ok')

   3、values_list('列1',‘列2’)
            Entry.objects.values_list("name","age")
            相当于:select name,age from...
            返回值:QuerySet,是一个有若干元祖所组成的列表:<QuerySet [('王宝强', 33), ('贾乃亮', 35), ('陈羽凡', 38)]>

    注意:values_list()可以用在QuerySet(查询结果集)后面比如:all().values_list()

def query_views(request):
    #查询Author实体中name 和 age的信息
    authors = Author.objects.values_list('name','age')
    print(authors)
    #< QuerySet[
    # ('老舍', 85), 
    # ('老舍', 85), 
    # ('巴金', 75), 
    # ('冰心', 80)] >
    for au in authors:
        print(au[0],au[1])
        # 老舍 85
        # 老舍 85
        # 巴金 75  
        # 冰心 80
    return HttpResponse('ok')

        4、get()
            只查找一条记录是使用,也只能返回一条记录,如果查询返回多条记录的话,则报错
            Entry.objects.get(id=1)
            相当于:select * from .... where id=1
            返回值:Author object

     注意:查询多于一条记录或者没有查询到结果都会抛出异常

      1、get() returned more than one Author -- it returned 2!(Exception Type: MultipleObjectsReturned)

      2、Author matching query does not exist(Exception Type: DoesNotExist)
        5、exclude()
            作用:对给定条件取反
            Entry.objects.exclude(id=1)
            相当于:select * from ...where not id=1
            返回值:<QuerySet [<Author: Author object>, <Author: Author object>]>
            Entry.objects.exclude(id=1,age=33)
            相当于:slect * from ...where not(id=1 and age=3)
        6、order_by()
            Entry.objects.order_by('列名1',‘列名2’...)
            指定按照字段进行排序,如果是多个字段,中间用,逗号隔开。默认是按照升序排列,需要降序的话,只需在列名前加”-“符号即可
            返回值:QuerySet(查询结果集,是一个封装了若干对象的列表)<QuerySet [<Author: Author object>, <Author: Author object>, <Author: Author object>]>

def query_views(request):
    #查询Author实体中的数据按照年龄升序排列
    authors = Author.objects.order_by('age')
    print(authors)
    #< QuerySet[
    # < Author: 巴金 >,
    # < Author: 冰心 >,
    # < Author: 老舍 >,
    # < Author: 老舍 >] >
    for au in authors:
        print(au.name,au.age)
        #巴金 75
        #冰心 80
        #老舍 85
        #老舍 85
    return HttpResponse('ok')

        7、filter()
            根据自定义条件查询结果集,可以是一个,也可以是多个,多个的话,条件用,逗号隔开。
            如果是多个条件的话,其内部是使用AND来进行条件连接的

    返回值:QuerySet(查询结果集,是一个封装了若干对象的列表)
            1、使用Entry的属性来作为filter()的条件
                示例:
                    1、Author.objects.filter(id=1)
                    相当于:select * from author where id=1
                    2、Author.object.filter(id=1,age=33)
                    相当于:select * from author where id=1 and age=3
            2、使用Field Lookups(查询谓词),完成复杂条件查询

     查询谓词:每一个独立的查询谓词就是一个独立的查询条件,所有支持使用查询条件的位置处,都允许适应查询谓词,get(),filter(),exclude()

      语法:属性__查询谓词=,双下划线
                1、__exact
                    作用:等值判断
                    Author.objects.filter(id__exact=1)
                    select * from author where id=1

      查看文档:https://docs.djangoproject.com/en/2.1/ref/models/querysets/

def query_views(request):
    #查询Author实体中邮箱属性包含字符a
    authors = Author.objects.filter(email__contains='a')
    return render(request,'query.html',locals())

                2、子查询
                    inner = Author.objects.filter(name__exact="王宝强").values("age")
                    authors = Author.objects.filter(age__gt=inner)等价于authors = Author.objects.filter(age__gt=inner[0]['age'])
3、修改操作
    1、修改单个对象
        1、通过get()获取要修改的实体对象
        2、通过实体对象修改属性值
        3、在通过实体对象的save()函数,实现保存
        auth = Author.objects.get(id=1)
        auth.name='宝强.王'
        auth.age = 45
        auth.save()
    2、批量修改(修改查询结果集的值)
        调用update()函数即可
        Author.objects.all().update(属性=值,....)
        说明:不能批量修改id
4、删除操作
    1、删除单个对象
        obj = Author.objects.get(id=1)
        obj.delete()
    2、批量删除
        Author.objects.all().delete()
5、F()操作 和 Q()操作
    1、F()操作
        作用:在执行中获取某列的值
        语法:F(‘列名’)
        from django.db.models import F
        Author.objects.all().update(age=F('age')+10)
    2、Q()操作

  作用:在查询条件中完成或(or)的操作

  语法:

    from django.db.models import Q

    Q(条件1)|Q(条件2)
        Author.objects.filter(id=1,age=35)//查询id为1并且age为35
        Author.objects.filter(Q(id_exact=1)|Q(age=35),name='王')//查询id为1或者age为35,并且那么为王的

  用法二:

    q = Q()    

    q.connector = 'or'   

    q.children.append(('id_exact',1))
    q.children.append(('age',35))
    Author.objects.filter(q)//查询id为1或者age为35

6、原生的数据库操作方法
    1、查询
        函数:raw()
        语法:Entry.objects.raw(sql语句)
    2、增删该
        def sql(requset):
            with connection.cursor() as cursor:
                sql = 'delete from index_author;'
                cursor.execute(sql)
                return render(......)
7、转发 与 重定向
    1、转发:
        转发就是将用户的请求发给另外一个视图进行处理,并将处理结果返回给用户请求的视图,最后响应给用户

  表现:地址栏不会发生改变

  原因:只有一次请求,所以地址栏就是最初请求的地址

def query_views(request):
    authors = Author.objects.filter(isActive=True)
    return render(request,'query.html',locals())
def delete_views(request,id):
    author = Author.objects.get(id=id)
    author.isActive=False
    author.save()
    return query_views(request)

  

    2、重定向:(推荐使用)
        重定向就是告知并响应给用户哪个视图可以处理用户的请求,然后用户在根据响应的地址进行请求,最终得到结果

  表现:地址栏会显示最后一次请求的地址

  原因:重定向导致浏览器向服务器发送了两次请求

from django.http import HttpResponseRedirect
def
query_views(request): authors = Author.objects.filter(isActive=True) return render(request,'query.html',locals()) def delete_views(request,id): author = Author.objects.get(id=id) author.isActive=False author.save() #重定向,参数是要重定向的地址 return HttpResponseRedirect('/02_query/')
from django.shortcuts import redirect
def
query_views(request): authors = Author.objects.filter(isActive=True) return render(request,'query.html',locals()) def delete_views(request,id): author = Author.objects.get(id=id) author.isActive=False author.save() #重定向,参数是要重定向的地址 return redirect('/02_query/')

 

from django.shortcuts import reverse
def
query_views(request): authors = Author.objects.filter(isActive=True) return render(request,'query.html',locals()) def delete_views(request,id): author = Author.objects.get(id=id) author.isActive=False author.save() #方向解析,参数是url的别名 url = reverse('query') #重定向,参数是要重定向的地址 return redirect(url)

 

 

1、使用后台管理Models
    后台登录地址:http://localhost:8000/admin
    1、创建后台管理员
        ./manage.py createsuperuser
        Username:
        Email Address:可以为空
        Password:
        Password(agin)
    2、基本管理
        1、在应用中的admin.py中注册要管理的数据
            1、admin.py
                作用:注册需要管理的Models,只有在此注册的Model才允许被管理,否则无法管理
            2、注册Model
                from .models import *
                admin.site.register(Entry)
            3、修改models.py处理显示内容
                后台默认效果可读性不高
                def __str__(self):
                    return self.name//将后台显示Author object(一条记录),修改为该对象的name属性值
                在实体类中属性添加verbose_name="姓名"
                name = models.CharField(max_length=30,verbose_name="姓名")//显示name字段为姓名
                name = models.CharField(max_length=30,verbose_name="aa")//显示name字段为Aa
            4、通过内部类Meta实现展现的属性
                允许为每个model类设置内部类Meta来设置其展示形式
                class Author(models.Model):
                    ....
                    ....
                    class Meta:
                        1、db_table:指定该实体类对应到表的名称,该操作必须先同步到数据库
                        2、verbose_name:定义该实体类在admin中显示的名字(复数形式),会在该属性值的后面加s
                        3、verbose_name_plural:效果同上,是单数形式
                        4、ordering:在后台显示数据时的排序规则,取值是一个列表,默认是升序,降序在字段前面加‘-’

        ordering = ["uphone"]:按照电话号码升序

        ordering = ["-uphone"]:按照电话号码降序

            5、ImageField数据类型
                在示例对象中添加该数据类型
                    1、pip install Pillow
                    2、picture = models.ImageField(
                        null=True,upload_to='static/upload/usrimg',verbose_name='头像')
                    null = True:因为数据表中原先有数据,现在添加新字段,需要允许为空
                    upload_to:表示上传后在项目中的保存路径
                    verbose_name:在后台显示的名字
    2、高级管理
        1、在admin.py中创建管理类,实现高级管理功能
            1、定义EntryAdmin类,继承自admin.ModelAdmin
            2、注册实体类
                class AuthorAdmin(admin.ModelAdmin):
                    pass
                admin.site.register(Author, AuthorAdmin)
            3、允许在EntryAdmin增加的属性
                1、list_display
                    作用:在显示实体信息的页面上,都显示哪些字段
                    取值:列表 或 元组
                2、list_display_links
                    作用:定义能够链接到具体实体页面的链接们
                    取值:由属性名组成的元组或列表
                    注意:取值必须要出现在list_display中,默认为list_display的第一个字段,
                3、list_editable
                    作用:定义在列表页面中允许被修改的字段
                    取值:由属性名组成的元组或列表
                    注意:list_editable中的值不能出现在list_display_links
                4、search_fields
                    作用:添加允许被搜索的字段
                    取值:由属性组成的元组或列表
                5、list_filter
                    作用:在列表的右侧增加过滤器,实现快速筛选
                    取值:由属性组成的元组或列表
                6、date_hierarchy
                    作用:在顶部增加一个时间选择器,所以取值必须是DateField 或 DateTieField的列
                7、fields
                    作用:在实体的详细页面中,显示哪些属性,并按照什么样的顺序显示
                    取值:由属性组成的元组或列表,空列表或元组无效
                8、fieldsets
                    作用:在实体的详细页面中,对属性进行分组
                    注意:fieldsets 与 fields不能共存
                    语法:
                        fieldsets = (

        #分组1
                            (‘当前分组的名称’,{'fields':(属性1,属性2...),‘classes’:(‘collapse’)}),

        #分组2
                            (‘当前分组的名称’,{'fields':(属性1,属性2...),‘classes’:(‘collapse’)}),
                            ......
                        )

      ‘classes’:(‘collapse’):表示可以被折叠

    9、filter_horizontal(“必须是具有多对多关系的属性”)和 filter_vertical(“必须是具有多对多关系的属性”)

      注意:

        当两个属性与raw_id_fields共存时,效果将会失效

      原图:

       filter_horizontal = ('publisher',):

      filter_vertical = ("publisher",)

    10、raw_id_fields("必须是具有一对多或多对多关系的属性")   

class BookAdmin(admin.ModelAdmin):
    list_display = ('title','publication_date')
    #book与publisher是多对一的关系,
    #book域author是多对多的关系
    raw_id_fields = ('publisher','author')
    filter_horizontal = ('author',)#此处域raw_id_fields("author")共存将失效

    原图:

      raw_id_fields = ('publisher','author')


2、Django连接查询(关系映射)
    1、一对一映射(1:1)
        1、什么是一对一
            A表中的一条记录只能与B表中的一条记录匹配关联

    B表中的一条记录也只能与A表中的一条记录相关联
            数据库中的实现:
                A表:设计主键
                B表:有主键,增加一列(作为外键),并应用A表中的主键值,还得增加一个唯一约束
        2、语法:

    在关联的两个类的任何一个类中,增加对另外一个类的应用

            属性 = models.OneToOneField(Author,null=True)
            author = models.OneToOneField(Author,null=True)
            +-----------+-------------+------+-----+---------+----------------+
            | Field     | Type        | Null | Key | Default | Extra          |
            +-----------+-------------+------+-----+---------+----------------+
            | id        | int(11)     | NO   | PRI | NULL    | auto_increment |
            | name      | varchar(30) | NO   |     | NULL    |                |
            | age       | int(11)     | NO   |     | NULL    |                |
            | author_id | int(11)     | YES  | UNI | NULL    |                |
            +-----------+-------------+------+-----+---------+----------------+    

    | wife | CREATE TABLE `wife` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(30) NOT NULL,
    `age` int(11) NOT NULL,
    `author_id` int(11) NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `author_id` (`author_id`),
    CONSTRAINT `wife_author_id_1672739f_fk_author_id` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8

#编写Wife实体了类,与Author做一对一关系映射
class Wife(models.Model):
    name = models.CharField(max_length=30,verbose_name="姓名")
    age = models.IntegerField(verbose_name='年龄')
    #指定一对一的关联关系,引用自Author实体
    author = models.OneToOneField(Author,verbose_name='丈夫')
    class Meta:
        db_table='wife'

       3、查询

            class Wife(models.Model):
                name = models.CharField(max_length=30,verbose_name='姓名')
                age = models.IntegerField(verbose_name="年龄")
                #增加一对一的关系映射
                author = models.OneToOneField(Author,null=True,verbose_name='丈夫')
            正向查询:通过wife 找 author

     #获取id为1的wife的信息
                w = Wife.objects.get(id=1)

     #在获取wife关联的author
                a = w.author

def oto_views(requset):
    #先获取i的为1的wife的信息
    wife = Wife.objects.get(id=1)
    #再获取对应的author
    author = wife.author
    return render(requset,'03_oto.html',locals())

            反向查询:通过author 找 wife
                a = Author.objects.get(id=1)
                w = a.wife
                wife 是由Django通过OneToOneField在Author中默认增加的一个属性,在数据库中没有体现
 2、一对多映射
        1、什么是一对多
            A表中的一条数据可以与B表中的任意多条数据匹配

    B表中的一条数据只能与A表中的一条数据相关联
        2、语法:

    在‘多’表中增加外键,对‘一’表表中的主键进行引用
            使用外键(Foreign Key)

    在‘多’实体中增加:
            属性 = models.ForeignKey(实体类)
            pub = models.ForeignKey(Publisher,null=True)
            +----+----------+------------------+--------+
            | id | title    | publication_date | pub_id |
            +----+----------+------------------+--------+
            |  1 | Python   | 1990-01-20       |      1 |
            |  2 | HTML/CSS | 1992-12-18       |   NULL |
            |  3 | Django   | 2018-08-18       |      3 |
            |  4 | HTML/CSS | 1992-02-18       |      2 |
            |  5 | JAVA     | 2018-08-19       |      3 |
            +----+----------+------------------+--------+  

   | book | CREATE TABLE `book` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(30) NOT NULL,
  `publication_date` date NOT NULL,
  `publisher_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `book_publisher_id_ac4b162a_fk_publisher_id` (`publisher_id`),#普通索引
  CONSTRAINT `book_publisher_id_ac4b162a_fk_publisher_id` FOREIGN KEY (`publisher_id`) REFERENCES `publisher` (`id`)
  ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |

        3、查询
            Book(M)和publisher(1)
                class Book(models.Model):
                    #增加一对多的关系
                    pub = models.ForeignKey(Publisher,null=True,verbose_name="出版社")
            1、正向查询 —— 通过Book 查询 Publisher
                book = Book.objects.get(id=1)
                publisher = book.pub

def otm_views(request):
    #先查询id为1的book的信息
    book = Book.objects.get(id=1)
    #在查询book关联publisher
    publisher=book.publisher
    return render(request,'04_otm.html',locals())

            2、反向查询 - 通过Publisher 查询 Book

     Django会通过ForeignKey()向关联的类中增加一个隐式属性:当前类_set,(当前类小写)
                p = Publisher.objects.get(id=1)
                bookset = p.book_set.all()//book_set是Django在Publisher实体类中添加book_set属性

 3、多对多映射
        1、什么是多对多
            A表中的一条记录可以与B表中的任意多条记录相关联
            B表中的一条记录可以与A表中的任意多条记录相关联
        2、在数据库中的体现
            必须创建第三张表,用于关联涉及到的两张表的数据
        3、语法:
            在涉及的到两个类中的任意一个类中,都可以对另外一个类的多对多的引用
                entry=models.ManyToManyField(Entry)
            示例:
                创建书籍与作者之间的多对多的引用
                    可以在书籍实体类中,增加对作者的引用
                    可以在作者实体类中,增加对书籍的引用
                class Book(models.Model):
                    ........
                    author=models.ManyToManyField(Author)

    +-----------+---------+------+-----+---------+----------------+
    | Field     | Type    | Null | Key | Default | Extra          |
    +-----------+---------+------+-----+---------+----------------+
    | id        | int(11) | NO   | PRI | NULL    | auto_increment |
    | book_id   | int(11) | NO   | MUL | NULL    |                |
    | author_id | int(11) | NO   | MUL | NULL    |                |
    +-----------+---------+------+-----+---------+----------------+
    | book_author | CREATE TABLE `book_author` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `book_id` int(11) NOT NULL,
      `author_id` int(11) NOT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `book_author_book_id_author_id_4fda6750_uniq` (`book_id`,`author_id`),#复合唯一索引book_id和author_id不能同时相同
      KEY `book_author_author_id_325bf96f_fk_author_id` (`author_id`),#普通索引
      CONSTRAINT `book_author_author_id_325bf96f_fk_author_id` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`),
      CONSTRAINT `book_author_book_id_19a45511_fk_book_id` FOREIGN KEY (`book_id`) REFERENCES `book` (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

        4、查询
            class Book(models.Model):
                ........
                author=models.ManyToManyField(Author)
            正向查询:通过Book找到对应的所有的Author
                #查询id为1的书籍的信息
                book = Book.objects.get(id=1)
                #查询book对应的所有的作者,通过关联属性查询对应的所有信息
                authors = book.author.all()

            反向查询:通过Author查询所有的Book
                Django会通过ManyToManyField()在关联类中增加一个隐式属性
                属性名:当前类_set,(类名小写)
                #查询id为2的作者信息
                author = Author.objects.get(id=2)
                #再查询对应的所有的书籍
                bookList = author.book_set.all()

def mtm_views(request):
    #正向查询
    book =Book.objects.get(id=2)
    authors = book.author.all()
    #反向查询,book_set
    author = Author.objects.get(id=3)
    bookList = author.book_set.all()
    return render(request,'05_mtm.html',locals())

 HTTP通信协议
    1、什么是HTTP
        HTTP:Hyper Text Transfer Protocol(超文本传输协议)
        作用:规范了数据是如何打包以及传送的
    2、请求消息
        由请求起始行,请求消息头,请求主体


        请求主题:
            post和put两种提交方式会产生请求主体
    3、响应消息
        由响应起始行,响应消息头,响应主体

1、HttpRequest
    1、HttpRequest介绍
        HttpRequest,在Django中是对请求对象的封装体现,会封装请求过程中所有的信息,
        在Django中,HTTPRequest被封装成了Request被自动传到了视图处理函数中
        以双下划线或单下划线开头的不是HTTPRequest协议中的属性或方法,是Django自动添加的
        ['COOKIES', 'FILES', 'GET', 'META', 'POST', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_encoding', '_get_post', '_get_raw_host', '_get_scheme', '_initialize_handlers', '_load_post_and_files', '_mark_post_parse_error', '_messages', '_post_parse_error', '_read_started', '_set_post', '_stream', '_upload_handlers', 'body', 'build_absolute_uri', 'close', 'content_params', 'content_type', 'csrf_processing_done', 'encoding', 'environ', 'get_full_path', 'get_host', 'get_port', 'get_raw_uri', 'get_signed_cookie', 'is_ajax', 'is_secure', 'method', 'parse_file_upload', 'path', 'path_info', 'read', 'readline', 'readlines', 'resolver_match', 'scheme', 'session', 'upload_handlers', 'user', 'xreadlines']
    2、HTTPRequest中的主要内容
        1、request.scheme:请求协议
        2、request.body:请求主题(只有post和put请求方式时才会有请求主题)
        3、request.path:请求路径
        4、request.get_host():请求的主机地址或域名
        5、request.method:获取请求方法
        6、request.GET:封装了GET请求方式提交的数据
        7、request.POST:封装了POST请求方式提交的数据

    说明:

     GET,POST的返回值都是一个字典,字典的值是一个列表,但是通过request.GET['key']取出的一个字符串,(为什么?)

     答案:Django中通过重写__getitem__方法实现的

'''
    QueryDict.__getitem__(key)
  返回给出的 key 的值。如果key 具有多个值,__getitem__()
    返回最后(最新)的值。如果 key 不存在,
    则引发django.utils.datastructures.MultiValueDictKeyError。(
    它是Python 标准KeyError 的一个子类,所以你仍然可以坚持捕获KeyError。)
    总结:Django中通过重写__getitem__方法实现的
'''

class MyDict():
    def __init__(self,iterable):
        self.data = iterable

    def __getitem__(self, item):
        return self.data[item][-1]

dict = {
    'name':['xdl','gj'],
    'age':[25]
}
myDict = MyDict(dict)
print(type(myDict))#<class '__main__.MyDict'>
print(myDict['name'])#gj

        8、request.COOKIES:封装了cookie的数据
        9、request.META:封装了请求的元数据
            request.META["HTTP_REFERER"]:封装了请求的源地址

def requset_views(request):
    #request,类型就是HTTPRequest
    #request,封装的是所有与请求相关的内容
    #print(dir(request))

    #请求协议(方案),http
    scheme = request.scheme
    #请求主体
    body = request.body
    #请求资源的具体路径,根相对路径,/01_requset/
    path = request.path
    #请求的主机地址或域名,127.0.0.1:8000
    host = request.get_host()
    #请求方式,GET
    method = request.method
    #get方式请求的数据,得到的是一个字典,<QueryDict: {}>
    get = request.GET
    #post方式请求数据,<QueryDict: {}>
    post = request.POST
    #cookie中的数据,返回的是一个字典
    # {'csrftoken': 'w1TDCKqZakTz9IKn94luPeFjefTsGdDnRqGxzXdGJ5yNOQaWfeJC5MbUw0KRPWzo',
    # 'sessionid': '702s33knczrluqmeh15m9rvbasptd39i'}
    cookies = request.COOKIES
    #请求元数据,返回的是一个字典
    meta = request.META
    return render(request,'01_request.html',locals())

    3、获取请求提交的数据
        1、get请求方式
            request.GET["名称"]
            1、使用表单提交数据
                <form></form>
            2、通过超链接拼接查询字符串
                <a href="地址?参数1&参数2..."></a>
                此种方式,属于http标准,任何语言都可以使用
                Django中通过URL传递参数
                    url(r'01_test/(\d+)',test_views)
                此种方式,非http标准的,属于Django标准
        2、post请求方式
            request.POST["名称"]
            CSRF:Cross-Site Request Forgery(伪装):跨站点伪装攻击


                解决方案:
                    1、取消CSRF的验证
                        删除settings.py中MIDDLEWARE中的'CsrfViewMiddleware'中间件


                    2、开放验证权限,无需验证,直接进入
                        在视图处理函数之上增加一个装饰器@crsf_protect

       需要引包:from django.views.decorators.csrf import csrf_protect
                    3、必须要通过验证后才可以请求
                        在模板中<form>下第一行增加:{% scrf_token %}
                        在表单里面会出现一个隐藏域,value是一个可变的字符串
                        <input type='hidden' name='csrfmiddlewaretoken'     value='hE2u8FkzeReMYlfzj8CUHPUwEVqURdc6C3Po5S7gNCT0DtF8pi02Xnq7WGhj0W87' />
    4、Django中的表单处理
        表单页面的get和post请求是由同一个视图(views)处理的,通过request.method判断

def login_views(request):
    if request.method == 'GET':
        return render(request,'03_login.html')
    else:
        return HttpResponse('用户名:%s,密码:%s'%(request.POST['uname'],request.POST['upwd']))

 2、使用forms模块处理表单
    1、forms模块的作用
        通过forms模块,允许将表单与class相结合,允许通过class生成表单
    2、使用forms模块
        1、创建forms.py文件(在应用中创建)
        2、导入forms
            form django import forms
        3、创建class,必须继承自forms.Form一个class对应成一个表单
            class LoginForm(forms.Form):
                pass
        4、在class中创建属性(不用创建提交按钮)
            一个属性对应一个表单控件

# 表示评论内容的表单控件
class RemarkForm(forms.Form):
    # 评论标题-文本框
    subject = forms.CharField(label='标题')
    # Email  - type=‘Email’
    email = forms.EmailField(label="邮箱")
    #评论内容-文本域
    message = forms.CharField(label="内容",widget=forms.Textarea)#widget=forms.PasswordInput表示密码框
    #好评,中平,差评-select
    topic_choices = (
                     (1,"好评"),
                     (2,"中评"),
                     (3,"差评"))
    topic = forms.ChoiceField(label='评价',choices=topic_choices)
    #是否保存
    isSaved = forms.BooleanField(label='是否保存')

    3、在模板中解析form对象
        1、注意
            1、需要自定义<form></form>
            2、需要自定义按钮<input type='submit'>
        2、处理方法
            在视图中创建forms.Form的对象,并发送到模板中
            示例:
                form = RemarkForm()
                return render(request,'xx.html',locals())
            1、手动解析
                在模板中:
                    {% for field in form %}
                        {{field.lable}}:表示控件前面显示的文本
                        {{field}}:表示的就是控件
                    {% endfor %}
            2、自动解析
                1、{{form.as_p}}
                    将form对象中的每个属性使用p标记包裹起来,再显示在网页上
                2、{{form.as_ul}}
                    将form对象中的每个属性使用li标签包裹起来,再显示在网页上
                    注意:必须手动提供<ol></ol>或<ul></ul>
                3、{{form.as_table}}
                    将form对象中的每个属性使用tr标签包裹起来,再显示在网页上
                    注意:必须手动提供<table></table>
    4、在视图中,通过forms.Form自动获取表单数据
        1、通过forms.Form的构造函数,接收post数据
            form = XXXForm(requset.POST)
        2、需要让form通过验证后,再取值(必须要验证)
            form.is_valid()
                返回True:提交的数据已经通过验证,允许接收表单提交的数据
                返回False:提交的数据验证未通过,无法取值
        3、获取表单中的数据
            通过form.cleaned_data(字典)接收提交的数据

def register_views(request):
    if request.method =="GET":
        form = RegisterForm()
        return render(request,'06_register.html',locals())
    else:
        form = RegisterForm(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            try:
                User.objects.get(uname=cd['uname'])
                return HttpResponse('用户名已存在')
            except ObjectDoesNotExist:
                User.objects.create(**cd)
                return HttpResponse("注册成功")

 1、forms模块
    1、forms的高级处理
        将Models和Forms结合到一起使用
        将Forms中的类和Models中的类关联到一起,实现属性的共享
        1、在forms.py中创建class,继承自forms.ModelForm
        2、创建内部类:Meta,关联Form和Model
            属性:
                1、model:指定要关联的Model类
                2、fields:指定从Model中取哪些字段生成控件
                    1、取值:"__all__",全部的属性都要生成控件
                    2、取值:列表或元祖,声明允许生成控件的属性名称
                3、labels:指定每个属性所关联的label,取值为字典
                    labels={
                        '属性名':"label文本",
                        '属性名':"label文本",
                        .........
                    }

#创建class表示登录的表单,要关联Users实体类
class UserLoginForm(forms.ModelForm):
    class Meta:
        #指定关联的model
        model = User
        #指定要生成的控件字段
        fields = ["uname","upwd"]
        #指定每个控件对应的label
        labels={
            "uname":"用户名",
            "upwd":"密码",
        }

    2、内置小部件
        1、什么是小部件
            小部件(widget),表示的是生成到页面中的控件的类型以及其他的html属性
        2、常用的小部件
            1、TextInput:type=“text”
            2、NumberInput:type=“number”
            3、PasswordInput:type=“password”
            4、EmailInput:type=“email”
            5、URLInput:type=”url“
            6、HiddenInput:type=“hidden”
            7、CheckboxInput:type=“checkbox”
            8、Textarea:<Textarea></Textarea>
            9、Select:<Select></Select>
        3、小部件的使用
            1、继承自forms.Form
                1、基本版
                    只指定控件的类型
                    属性=forms.CharField(
                        lable="标签",
                        widget=forms.小部件的类型
                        )
                    示例:
                        upwd=forms.CharField(label=“密码”,widget=forms.PasswordInput)
                2、高级版
                    指定控件类型之外还允许设置html属性
                    属性=forms.CharField(
                            label="标签",
                            widget=forms.小部件类型(
                                attrs = {
                                    "html属性名":"属性值",
                                    "html属性名":"属性值",
                                    ......
                                }
                            )

      )

class WidgetForm(forms.Form):
    uname = forms.CharField(
        label="用户名称",
        widget=forms.TextInput(
            attrs={
                'name':'user_name',
                'placeholder':"请输入用户名称",
                'class':'form-control',
            }
        )
    )
    upwd = forms.CharField(
        label="用户密码",
        widget=forms.PasswordInput(
            attrs={
                'name':'user_pwd',
                'placeholder':'请输入密码',
                'class':'form-control',
            }
        )
    )

            2、继承自forms.ModelForm
                class Widget2Form(forms.ModelForm):
                    class Meta:
                        model = User
                        fields= "__all__"
                        labels={
                            "属性1":"标签1",
                            "属性2":"标签2",
                            ....
                        }
                        widgets={
                            "属性1":forms.小部件类型(attrs={}),
                            "属性2":forms.小部件类型(attrs={}),
                            ........
                        }

class Widget2Form(forms.ModelForm):
    class Meta:
        model=User
        fields=("uname","upwd")
        labels={
            "uname":'用户名称',
            "upwd":"用户密码",
        }
        widgets={
            'uname':forms.TextInput(
                attrs={
                    "placeholder":'请输入用户名'
                }
            ),
            'upwd':forms.PasswordInput(
                attrs={
                    'placeholder':"请输入密码"
                }
            )
        }

 2、cookies
    1、什么是cookies
        cookies是一种数据的存储技术,只能保存字符串
        允许将一段文本保存在客户端上(浏览器)的一种技术,并可以长时间保存
    2、cookies的使用场合
        1、记住密码
        2、保存搜索关键词
    3、在Django中使用cookies
        1、设置cookies的值(将数据保存客户端)
            语法:
                响应对象.set_cookie(key,value,[expires])
                    key:cookie的名字
                    value:cookie的值
                    expires:保存时间,以s为单位,如果不给该参数,则浏览器关闭,cookie失效
                示例:
                    响应对象.set_cookie('uname','xdl',60*60*24*366)
                响应对象:HttpResponse,render,HttpResponseRedirect,redirect
            1、不使用模板(HttpResponse)
                resp = HttpResponse("给客户端的一句话")
                resp.set_cookie('key','value',expires)
                return resp
            2、使用模板(render)
                resp = render(reuqest,'xxx.html',locals())
                resp.set_cookie('key','value',expires)
                return resp
            3、重定向(HttpResponseRedirect/redirect)
                resp = HttpResponseRedirect('/地址/')
                resp.set_cookie('key','value',expires)
                return resp
        2、获取cookies的值(将数据从客户端中获取出来)
            通过request.COOKITES(返回的是一个字典,通过键值可以取值)
            获取当前访问站点下所有的cookies的信息

  3、删除cookie

    响应对象.delete_cookie('key')
3、session-会话
    1、什么是session
        session(会话),实际上就是在服务器上为每个浏览器开辟的一段空间,用于保存相关的请求信息


    2、session的使用场合
        session也是为了存储数据而存在的
        通常会把服务器经常要用到的数据保存进去
    3、Django中使用session
        1、设置session的值
            request.session['key']=value
            request.session.set_expiry(time):
            设置session的过期时间,如果设置为0的话,则表示关闭浏览器session就失效
        2、获取session的值
            value = request.session['key']                
            value = request.session.get('key')
        3、删除session的值
            del request.session['key']
        4、在setting.py中,有关session的设置
            1、SESSION_COOKIE_AGE
                作用:设置sessionID在cookies中的保存时长,默认为15天
                示例:
                    SESSION_COOKIE_AGE=60*6024
            2、SESSION_EXPIRE_AT_BROWSER_CLOSE(建议使用)
                作用:设置关闭浏览器时清除服务器上对象的session空间
                示例:
                    SESSION_EXPIRE_AT_BROWSER_CLOSE = True

cookie 存取中文

def setCookie_views(request):
    uname = '张三丰'
    #将uname转化为unicode
    uname = json.dumps(uname)
    resp = HttpResponse('set cookie ok')
    resp.set_cookie('name',uname)
    return resp
def getCookie_views(requset):
    uname = requset.COOKIES['name']
    #将unicode码转换为中文
    uname = json.loads(uname)
    return HttpResponse(uname)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <script type="text/javascript" src="/static/js/jquery-1.11.3.js"></script>
    <script type="text/javascript" src="/static/js/jquery.cookie.js"></script>
    <script>
        $(function(){
            var uname = $.cookie('name')
            //将Unicode码转换为中文
            uname = JSON.parse(uname)
            console.log(uname)
        });
    </script>
</body>
</html>

 上传图片

  前段页面: 

    上传图片  

<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}
     <input type="file" name="pic" id="pic">
    <button type="submit">提交</button>
</form>

    访问图片:通过views函数返回这个对象集合,然后在前端循环获取图片路径.url

{% for show in p %}
        {% if show.pic  %}
        <img src="{{ show.pic.url }}">
        {% endif %}
    {% endfor %}

 

  后端配置:

    配置settings文件

MEDIA_ROOT = os.path.join(BASE_DIR,'media').replace('\\','/')
MEDIA_URL = '/media/'

    配置urls文件,主路由文件

from django.conf.urls import url, include
from django.contrib import admin
from sale import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^$',views.index,name='index'),
    url(r'^userinfo/',include('userinfo.urls')),
]+ static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)

    views.py视图

def salecar(request):
        new_a = Aid()#实体类
        pic = request.FILES.get('pic')
        new_a.pic = pic
        new_a.save()
        return render(request,'infomessage.html')

 

posted @ 2018-08-17 04:24  xdl_smile  阅读(617)  评论(0编辑  收藏  举报