zoukankan      html  css  js  c++  java
  • django

     参考:http://www.cnblogs.com/wupeiqi/articles/5237704.html

    http://www.cnblogs.com/wupeiqi/articles/5341480.html

    http://www.cnblogs.com/wupeiqi/articles/5246483.html

    客户端访问服务器的时候,访问对应函数,函数会返回字符串到客户端
    1、django请求生命周期:
      -》URL对应关系(匹配) -》 视图函数 -》返回用户字符串;
      -》URL对应关系(匹配) -》 视图函数 -》打开一个HTML文件,读取内容

    安装

    mysite
        mysite             #对整个程序进行配置
            -init
            -setting    #配置文件
            -url        #URL对应关系
            -wsgi        #遵循WSGI规范,uwsgi + nginx
        -manage.py        #管理Django程序:
                        -python manage.py
                        -python manage.py startapp xx 创建app
                        -python manage.py makemigrations
                        -python manage.py migrate

    wsgi:遵循wsgi规则的是以下东西

      'cgi': CGIServer,
        'flup': FlupFCGIServer,
        'wsgiref': WSGIRefServer,
        'waitress': WaitressServer,
        'cherrypy': CherryPyServer,
        'paste': PasteServer,
        'fapws3': FapwsServer,
        'tornado': TornadoServer,
        'gae': AppEngineServer,
        'twisted': TwistedServer,
        'diesel': DieselServer,
        'meinheld': MeinheldServer,
        'gunicorn': GunicornServer,
        'eventlet': EventletServer,
        'gevent': GeventServer,
        'geventSocketIO':GeventSocketIOServer,
        'rocket': RocketServer,
        'bjoern' : BjoernServer,
        'auto': AutoServer,

    pip3 install django

    安装完毕后,python目录就会增加两个文件,然后将这个目录C:Python36Scripts增加到环境变量

    django-admin.exe  startproject laoniu

    运行命令提示符,D盘目录将会增加laoniu文件夹;

    命令提示符,进入该目录,输入命令python manage.py runserver 127.0.0.1:8001

     pycharm启用django

    选中对应项目,然后启动(修改访问端口也是这里硒鼓)

    若是没有对应django server,需要编辑结构,选中左上角的+,增加上去

     

     创建app

    chouti
      -chouti
        -配置
      -主站 app
      -后台管理 app


    python manage.py startapp cmdb
    python manage.py startapp openstack

    python manage.py startapp makemigrations
    python manage.py startapp xxxx

    app:

      makemigrations:      修改数据库表结构的记录

      admin        Django为我们提供的后台管理

      apps          配置当前app

      models        ORM,写指定的类,通过命令可以创建数据库结构

      tests          单元测试

      views        业务代码

    1.配置模板的路径

    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR),"templates"],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]

    2.配置静态目录

    静态文件对应客户端请求,需要在settings配置文件最后加上


    STATICFIES_DIRS = (
    # 这里必须要有逗号
    os.path.join(BASE_DIR,'static'),
    )

    settings文件注释 MIDDLEWARE 的'django.middleware.csrf.CsrfViewMiddleware',
    MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]

    4、编写程序

    a.url.py
      /inde/ -> func

    b. views.py(参数是必须的,包含了所有的客户端请求信息)
      def func(request):

        ...
        return HttpResponse('字符串')      return HttpResponse(bytes('字符串')),可以返回字符串以及字节
        return render(request,'index.html',{{''}})  渲染页面
        return ret('URL')            页面跳转

    c. 模板语言
      return render(request,'index.html',{{'l1':[11,22,33]}})
      {%for item in..%}
        <h1>{{item}}</h1>
      {{endfor}}

      只要有for就有forloop

      forloop.counter      counter的意思是循环一次+1,初始值为0

      forloop.revcounter      counter的意思是循环一次-1,最后值为0

      forloop last


    {{for}}

      {{if num = 1}}
        return true
      {{endif}}

    {{endfor}}


    request.Get:  获取数据
    request.POAT:  提交数据
    request.FILES  #获取文件信息
     
    u = request.POST.get('user')     #get只能获取一个值  radio
    v = request.POST.getlist('favor')  #getlist 获取多个值,列表;一般用于CheckBox,select-option多选组合等


     # django处理文件一般是用request.FILES,request.FILES.get是获取文件信息,默认返回是文件名称
            obj = request.FILES.get('file')
            print(obj,type(obj))
    
            import os
            file_path = os.path.join('upload',obj.name)
    #上传文件
            f = open(file_path,mode='wb')
            # chunks 相当于一段段获取文件信息
            for i in obj.chunks():
                f.write(i)
            f.close()
    #要上传文件,需要再form上面加上enctype="multipart/form-data"#}
    <form action="/login/" method="post" enctype="multipart/form-data"> </form>
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    {#要上传文件,需要再form上面加上enctype="multipart/form-data"#}
        <form action="/login/" method="post" enctype="multipart/form-data">
            <p>
                <input type="text"name="user" placeholder="用户名"/>
            </p>
             <p>
                <input type="password"name="pwd" placeholder="密码"/>
            </p>
            <p><input type="radio" name="gender" value="1" /><input type="radio" name="gender" value="2" /><input type="radio" name="gender" value="3" />
            </p>
            <p>
                篮球<input type="checkbox" name="favor" value="11" />
                足球<input type="checkbox" name="favor" value="22" />
                排球<input type="checkbox" name="favor" value="33" />
            </p>
            <p>
    {#            多了multiple,可以多选,所以后端必须写收取多个值的getlist#}
                <select name="city" multiple>
                    <option value="sh">上海</option>
                    <option value="bj">北京</option>
                    <option value="tj">天津</option>
                </select>
            </p>
    
            <p>
                <input type="file" value="上传文件" name="file" />
            </p>
    
            <input type="submit" value="提交" />
        </form>
    </body>
    </html>
    login.html

    获取字典信息:

    user_dict.keys    #字典的key

    user_dict.values    #字典的value

    user_dict.items    #字典的key和value

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
      <ul>
          {% for k in user_dict.keys %}
                <li>{{ k }}</li>
          {% endfor %}
            <p></p>
          {% for v in user_dict.values %}
                <li>{{ v }}</li>
          {% endfor %}
            <p></p>
          {% for k,v in user_dict.items %}
                <li>{{ k }} - {{ v }}</li>
          {% endfor %}
    
      </ul>
    
    </body>
    </html>
    index.html

    类的操作:

      客户端发送信息到服务器,经过from django.views import View的View的dispatch,将方法转换为小写英文之后,进行反射到对应的方法

        def dispatch(self, request, *args, **kwargs):
            '''
            调用父类中的dispatch,进行重写,这样可以实现类似装饰器那样的功能
            '''
            print('before')
            result = super(Home,self).dispatch(request, *args, **kwargs)
            print('after')
            return result
    from django.shortcuts import render
    from django.shortcuts import HttpResponse
    
    # Create your views here.
    
    def index(request):
        return HttpResponse('Index')
    
    from django.views import View
    class Home(View):
    
        def dispatch(self, request, *args, **kwargs):
            '''
            调用父类中的dispatch,进行重写,这样可以实现类似装饰器那样的功能
            '''
            print('before')
            result = super(Home,self).dispatch(request, *args, **kwargs)
            print('after')
            return result
    
        def get(self,request):
            '''
            如果是get方法获取,则执行这个方法
            :param request:
            :return:
            '''
            print(request.method)
            return render(request,'home.html')
        def post(self,request):
            '''
            如果是post方法获取,则执行这个方法
            :param request:
            :return:
            '''
            print(request.method)
            return render(request,'home.html')
    viess.py
    """day19 URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/2.0/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  path('', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.urls import include, path
        2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
    """
    from django.contrib import admin
    from django.urls import path
    from migrations import views
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('index/', views.index),
    
        # 关联类的固定写法,关联类Home的as_view方法
        path('home/', views.Home.as_view()),
    ]
    url.py

    一、路由系统,URL

      

    1、url(r'^index/', views.index),    
           url(r'^home/', views.Home.as_view()),
        2、url(r'^detail-(d+).html', views.detail),  
        3、url(r'^detail-(?P<nid>d+)-(?P<uid>d+).html', views.detail)(推荐使用这个,配合下图的代码使用)
      4、url('index/',views.index,name='indexx'),
    
    
      url.py
      url(r'^datail-(d+).html', views.datail),
      
      views.py
      def datail(request,nid):
      user_info = USER_DICT[nid]
      return render(request,'detail.html',{"user_info":user_info})

      index.html
       {% for k,v in user_dict.items %}
    <li> <a target="_blank" href="/datail-{{ k }}.html">{{ v.username }}</a></li>
      {% endfor %}
      
      

      建议使用的方法:

      

      url.py:  url('index/',views.index,name='indexx'),
      
     <form action='{% url "indexx" %}' method="post">
            <p>
                <input type="text" name="user" placeholder="用户名" />
            </p>
              <p>
                <input type="text" name="email" placeholder="邮箱" />
            </p>
              <p>
                <input type="submit" value="提交" />
            </p>
        </form>
    name:
      对URL路由关系进行命名,以后可以根据此名称生成自己想要的URL
      
    url('index/',views.index,name='indexx')
    url('index/(d+)/(d+)/',views.index,name='indexx')
    url('index/(?P<pid>d+)/(?P<uid>d+)/',views.index,name='indexx')


    模板语言:
      {% url "indexx" %}
      {% url "indexx 3 4" %}

    注意:request.path_info    #当前的URL

     当请求过来的时候,优先匹配project同名目录下的urls.py,然后再分发给其他目录下的urls.py


    默认值



      

    二、视图

    三、模板

    四、ORM操作

       

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'back_logs',
            'USER':'root',
            'PASSWORD': 'Choice123',
            'HOST':'localhost',
            'PORT':'3306'
        }
    }
    # 如果想用mysql数据库
    # DATABASES = {
    #     'default': {
    #         'ENGINE': 'django.db.backends.mysql',
    #         'NAME': 'dbname',
    #         'USER':'root',
    #         'PASSWORD': 'XXX',
    #         'HOST':'',
    #         'PORT':','
    #     }
    # }

     修改之后,需要再init.py文件里面写入代码

    import pymysql
    pymysql.install_as_MySQLdb()

    
    
    

      select * from tb where id > 1

      #对应关系

      models.tb.objects.filter(id__gt=1)    #id大于1

      models.tb.objects.filter(idt=1)      #id等于1

      models.tb.objects.filter(id__lt=1)    #id小于1

      创建类

        1、根据类自动创建数据库表

          #app下的models.py 先写类

          

    # 必须要继承models.Model
    # 表名叫:app01_userinfo
    class UserInfo(models.Model):
    
    
        # id列,自增,主键(django自动创建)
        # 用户名列,字符串类型,指定长度
        username = models.CharField(max_length=32)
        # 密码列,字符串类型,指定长度
        password = models.CharField(max_length=64)

          注册app:

          settings.py文件下,找到INSTALLED_APPS,增加app目录名称(# django会根据这里找app01目录下的migrations)
      
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        # django会根据这里找app01目录下的migrations
        'app01',
    ]

         然后执行命令: 

                  python manage.py makemigrations

               python manage.py migrate

     model操作

       参考:https://www.cnblogs.com/wupeiqi/articles/6216618.html 

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }
    
    # 如果想用mysql数据库
    # DATABASES = {
    #     'default': {
    #         'ENGINE': 'django.db.backends.mysql',
    #         'NAME': 'dbname',
    #         'USER':'root',
    #         'PASSWORD': 'XXX',
    #         'HOST':'',
    #         'PORT':','
    #     }
    # }
    settings.py设置数据库

     注意:如果需要使用mysql,但是我们之前使用的是pymysql,不是django默认的MySQLdb模块连接mysql,所以需要在project同名文件夹下的__init__.py文件下增加代码

    import pymysql
    pymysql.install_as_MySQLdb()

        2、根据类对数据库表中的数据进行各种操作

    from django.shortcuts import render
    from django.shortcuts import HttpResponse
    from django.shortcuts import redirect
    
    # Create your views here.
    
    
    def login(request):
        return HttpResponse('login')
    
    from app01 import models
    def orm(request):
    
        # 创建信息方法一(推荐使用)
        models.UserInfo.objects.create(
            username = 'root',
            password='123'
        )
        # 方法一可以写成
        # dic = {'username' : 'root','password':'123'}
        # models.UserInfo.objects.create(**dic)
    
        # 创建信息方法二
        # obj = models.UserInfo(username = 'root', password='123')
        # obj.save()
        return HttpResponse('orm')
    创建数据
    v = models.Business.objects.all()

    # 查找特定的列,类似select id,caption from business
    v = models.Business.objects.all().values('id','caption')
    from django.shortcuts import render
    from django.shortcuts import HttpResponse
    from django.shortcuts import redirect
    
    # Create your views here.
    
    
    def login(request):
        return HttpResponse('login')
    
    from app01 import models
    def orm(request):
    
        # 创建信息方法一(推荐使用)
        # models.UserInfo.objects.create(
        #     username = 'root',
        #     password='123'
        # )
        # 方法一可以写成
        # dic = {'username' : 'root','password':'123'}
        # models.UserInfo.objects.create(**dic)
    
        # 创建信息方法二
        # obj = models.UserInfo(username = 'root', password='123')
        # obj.save()
    
    
        #
        # 表里面所有的数据都被取出,返回QuerySet类型,理解为列表[obj,obj,obj]
        # result = models.UserInfo.objects.all()
        # print(result)
        # for row in result:
        #     print(row.id,row.username,row.password)
    
        # 根据条件查出表里的数据,返回QuerySet类型
        result = models.UserInfo.objects.filter(username='root')
        for row in result:
            print(row.id, row.username, row.password)
    
        return HttpResponse('orm')
    查询数据
    from django.shortcuts import render
    from django.shortcuts import HttpResponse
    from django.shortcuts import redirect
    
    # Create your views here.
    
    
    def login(request):
        return HttpResponse('login')
    
    from app01 import models
    def orm(request):
    
        # 创建信息方法一(推荐使用)
        # models.UserInfo.objects.create(
        #     username = 'root',
        #     password='123'
        # )
        # 方法一可以写成
        # dic = {'username' : 'root','password':'123'}
        # models.UserInfo.objects.create(**dic)
    
        # 创建信息方法二
        # obj = models.UserInfo(username = 'root', password='123')
        # obj.save()
    
    
        #
        # 表里面所有的数据都被取出,返回QuerySet类型,理解为列表[obj,obj,obj]
        # result = models.UserInfo.objects.all()
        # print(result)
        # for row in result:
        #     print(row.id,row.username,row.password)
    
        # 根据条件查出表里的数据,返回QuerySet类型
        # result = models.UserInfo.objects.filter(username='root')
        # for row in result:
        #     print(row.id, row.username, row.password)
    
    
        # 删除
        # 删除表的所有数据
        models.UserInfo.objects.all().delete()
    
        # 删除表里id为1的数据
        models.UserInfo.objects.filter(id=1).delete()
    
    
        return HttpResponse('orm')
    删除数据
    from django.shortcuts import render
    from django.shortcuts import HttpResponse
    from django.shortcuts import redirect
    
    # Create your views here.
    
    
    def login(request):
        return HttpResponse('login')
    
    from app01 import models
    def orm(request):
    
        # 创建信息方法一(推荐使用)
        # models.UserInfo.objects.create(
        #     username = 'root',
        #     password='123'
        # )
        # 方法一可以写成
        # dic = {'username' : 'root','password':'123'}
        # models.UserInfo.objects.create(**dic)
    
        # 创建信息方法二
        # obj = models.UserInfo(username = 'root', password='123')
        # obj.save()
    
    
        #
        # 表里面所有的数据都被取出,返回QuerySet类型,理解为列表[obj,obj,obj]
        # result = models.UserInfo.objects.all()
        # print(result)
        # for row in result:
        #     print(row.id,row.username,row.password)
    
        # 根据条件查出表里的数据,返回QuerySet类型
        # result = models.UserInfo.objects.filter(username='root')
        # for row in result:
        #     print(row.id, row.username, row.password)
    
    
        # 删除
        # # 删除表的所有数据
        # models.UserInfo.objects.all().delete()
        #
        # # 删除表里id为1的数据
        # models.UserInfo.objects.filter(id=1).delete()
    
    
        # 更新
        # 表中所有数据的列password改为666
        models.UserInfo.objects.all().update(password=666)
        # 表中id为3 的行,password字段改为6669
        models.UserInfo.objects.filter(id=3).update(password=6669)
    
        return HttpResponse('orm')
    改数据
    from django.shortcuts import render
    
    from app01 import models
    # Create your views here.
    
    def business(request):
    
        # 获取数据,保存为queryset列表
        v = models.Business.objects.all()
    
        # 查找特定的列,类似select id,caption from business,返回的是字典
        v2 = models.Business.objects.all().values('id','caption')
    
        # 查询获取的结果,返回的是元组
        v3 = models.Business.objects.all().values_list('id','caption')
    
        return render(request,'business.html',{'v':v,"v2":v2,"v3":v3})
    获取表单数据的三种方式
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>业务线列表(对象)</h1>
            {% for row in v %}
                <ul>{{ row.id }}-{{ row.caption }}-{{ row.code }}</ul>
            {% endfor %}
         <h1>业务线列表(字典)</h1>
            {% for row in v2 %}
                <ul>{{ row.id }}-{{ row.caption }}</ul>
            {% endfor %}
    
        <h1>业务线列表(元组)</h1>
            {% for row in v3 %}
                <ul>{{ row.0 }}-{{ row.1 }}</ul>
            {% endfor %}
    
    </body>
    </html>
    获取表单数据的三种方式.html

    外键:

      

    # 与表Business关联,to是关联的表,to_field是关联的字段
    b = models.ForeignKey(to="Business",to_field='id',on_delete=models.CASCADE)
    如果没有明确写明主键,默认id就是外键
     当删除关联表中的数据时,当前表与其关联的行的行为
                                            - models.CASCADE,删除关联数据,与之关联也删除
                                            - models.DO_NOTHING,删除关联数据,引发错误IntegrityError
                                            - models.PROTECT,删除关联数据,引发错误ProtectedError
                                            - models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
                                            - models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
                                            - models.SET,删除关联数据,
                                                          a. 与之关联的值设置为指定值,设置:models.SET(值)
                                                          b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)

    
    
    from django.db import models
    
    # Create your models here.
    
    class Business(models.Model):
    
        # 没写id,所以django自动生成
        #
        caption = models.CharField(max_length=32)
        # 设置显示文字是英文还是中文;
        # null=True可以为空
        # default='默认值' 设置新增列的默认值
        code = models.CharField(max_length=32,null=True,default='默认值')
    
    
    class Host(models.Model):
    
        # django会自动生成id,但是也能自己写,需要加上primary_key=True,AutoField整形自增
        nid = models.AutoField(primary_key=True)
    
        # 主机名,字符串,最大长度32位;db_index=True代表创建索引
        hostname = models.CharField(max_length=32,db_index=True)
        # ip,字符串类型,但是django会自动帮我验证,protocol='both'意思是ipv4以及ipv6都支持
        ip = models.GenericIPAddressField(protocol='both',db_index=True)
        # 端口,数字类型
        port = models.IntegerField()
    
        # 与表Business关联,to是关联的表,to_field是关联的字段
        b = models.ForeignKey(to="Business",to_field='id',on_delete=models.CASCADE)
    models.py

     用.(点)获取关联表信息

    用双下划线__获取字符串里面的跨表信息

    # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为字典类型
    v2 = models.Business.objects.all().values('nid', 'hostname', 'b_id', 'b__caption')
    print(type(v2))

    创建多对多:

      方式一:自定义关系表

     

    from django.db import models
    
    # Create your models here.
    
    class Business(models.Model):
    
        # 没写id,所以django自动生成
        #
        caption = models.CharField(max_length=32)
        # 设置显示文字是英文还是中文;
        # null=True可以为空
        # default='默认值' 设置新增列的默认值
        code = models.CharField(max_length=32,null=True,default='默认值')
    
    
    class Host(models.Model):
    
        # django会自动生成id,但是也能自己写,需要加上primary_key=True,AutoField整形自增
        nid = models.AutoField(primary_key=True)
    
        # 主机名,字符串,最大长度32位;db_index=True代表创建索引
        hostname = models.CharField(max_length=32,db_index=True)
        # ip,字符串类型,但是django会自动帮我验证,protocol='both'意思是ipv4以及ipv6都支持
        ip = models.GenericIPAddressField(protocol='both',db_index=True)
        # 端口,数字类型
        port = models.IntegerField()
    
        # 与表Business关联,to是关联的表,to_field是关联的字段
        b = models.ForeignKey(to="Business",to_field='id',on_delete=models.CASCADE)
    
    
    class Application(models.Model):
        '''
        应用
        '''
        name = models.CharField(max_length=32)
    
    
    
    class HostToApp(models.Model):
        '''
        host app关联
        '''
        hobj = models.ForeignKey(to=Host,to_field='nid',on_delete=models.CASCADE)
        aobj = models.ForeignKey(to=Application,to_field='id',on_delete=models.CASCADE)
    自定义关系表

      方式二:自动创建关系表

     缺点:无法直接对第三张表进行操作

      

    from django.db import models
    
    # Create your models here.
    
    class Business(models.Model):
    
        # 没写id,所以django自动生成
        #
        caption = models.CharField(max_length=32)
        # 设置显示文字是英文还是中文;
        # null=True可以为空
        # default='默认值' 设置新增列的默认值
        code = models.CharField(max_length=32,null=True,default='默认值')
    
    
    class Host(models.Model):
    
        # django会自动生成id,但是也能自己写,需要加上primary_key=True,AutoField整形自增
        nid = models.AutoField(primary_key=True)
    
        # 主机名,字符串,最大长度32位;db_index=True代表创建索引
        hostname = models.CharField(max_length=32,db_index=True)
        # ip,字符串类型,但是django会自动帮我验证,protocol='both'意思是ipv4以及ipv6都支持
        ip = models.GenericIPAddressField(protocol='both',db_index=True)
        # 端口,数字类型
        port = models.IntegerField()
    
        # 与表Business关联,to是关联的表,to_field是关联的字段
        b = models.ForeignKey(to="Business",to_field='id',on_delete=models.CASCADE)
    
    
    class Application(models.Model):
        '''
        应用
        '''
        name = models.CharField(max_length=32)
        # 第三张表自动生成
        r = models.ManyToManyField('Host')
    自动创建关系表

      obj = Application.objects.get(id=1)

      obj.name

    若需要对第三表操作,则使用如下方法:

    增加:

      obj.r.add(1)       增加关系1对1

      obj.r.add(2)       增加关系1对二

      obj.r.add(2,3,4)       增加关系1对2,1对3,1对4

      obj.r.add(*[1,2,3,4])   增加关系1对1,1对2,1对3,1对4

    删除:

      obj.r.remove(1)         删除关系1对1

      obj.r.remove(2,4)      删除关系1对2,1对4

      obj.r.remove(*[1,2,3])     删除关系1对1,1对2,1对3

      obj.r.clear()        删除只要application是1的关系

      obj.r.set([3,5,7])      删除除了1对3,1对5,1对7之外所有的关系

    获取:

      obj.r.all()        这里就是增加 b_list = models.Host.objects.all() 后面all的方法;obj.r相当于 models.Host.objects。

    model操作补充

    单表

    1.修改表名;类下定义一个类,Meta

    2.联合索引;

    from django.db import models
    
    # Create your models here.
    class UserInfo(models.Model):
        nid = models.AutoField(primary_key=True)
        username = models.CharField(max_length=32)
        email = models.CharField(max_length=32)
    
        class Meta:
            # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
            db_table = "table_name"
    
            # 联合索引
            # 最左前缀的模式:select * from table_name where username ='xx'
            # select * from table_name where username ='xx' and email = 'xx'
            # 前面两个都很快,但是如果没有了最左的那个,这里是uername,速度会非常慢
            index_together = [
                # ("pub_date", "deadline"),
                ("username", "email"),
            ]
    
            # 联合唯一索引
            unique_together = (("driver", "restaurant"),)
    
            # admin中显示的表名称,admin里面就会变成上课记录s
            verbose_name = '上课记录'
    
            # verbose_name加s,表名就会变成上课记录
            verbose_name_plural = '上课记录'
    View Code

    一对多,一对一,多对多

    django现在的版本会对外键关联的表的数据都删除

    ForeignKey(ForeignObject) # ForeignObject(RelatedField)
            to,                         # 要进行关联的表名
            to_field=None,              # 要关联的表中的字段名称
            on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为
                                            - models.CASCADE,删除关联数据,与之关联也删除
                                            - models.DO_NOTHING,删除关联数据,引发错误IntegrityError
                                            - models.PROTECT,删除关联数据,引发错误ProtectedError
                                            - models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
                                            - models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
                                            - models.SET,删除关联数据,
                                                          a. 与之关联的值设置为指定值,设置:models.SET(值)
                                                          b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
    
                                                            def func():
                                                                return 10
    
                                                            class MyModel(models.Model):
                                                                user = models.ForeignKey(
                                                                    to="User",
                                                                    to_field="id"
                                                                    on_delete=models.SET(func),)
            related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
            related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
            limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:
                                        # 如:
                                                - limit_choices_to={'nid__gt': 5}
                                                - limit_choices_to=lambda : {'nid__gt': 5}
    
                                                from django.db.models import Q
                                                - limit_choices_to=Q(nid__gt=10)
                                                - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                                                - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
            db_constraint=True          # 是否在数据库中创建外键约束
            parent_link=False           # 在Admin中是否显示关联数据
    
    
        OneToOneField(ForeignKey)
            to,                         # 要进行关联的表名
            to_field=None               # 要关联的表中的字段名称
            on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为
    
                                        ###### 对于一对一 ######
                                        # 1. 一对一其实就是 一对多 + 唯一索引
                                        # 2.当两个类之间有继承关系时,默认会创建一个一对一字段
                                        # 如下会在A表中额外增加一个c_ptr_id列且唯一:
                                                class C(models.Model):
                                                    nid = models.AutoField(primary_key=True)
                                                    part = models.CharField(max_length=12)
    
                                                class A(C):
                                                    id = models.AutoField(primary_key=True)
                                                    code = models.CharField(max_length=1)
    
        ManyToManyField(RelatedField)
            to,                         # 要进行关联的表名
            related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
            related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
            limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:
                                        # 如:
                                                - limit_choices_to={'nid__gt': 5}
                                                - limit_choices_to=lambda : {'nid__gt': 5}
    
                                                from django.db.models import Q
                                                - limit_choices_to=Q(nid__gt=10)
                                                - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                                                - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
            symmetrical=None,           # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段
                                        # 做如下操作时,不同的symmetrical会有不同的可选字段
                                            models.BB.objects.filter(...)
    
                                            # 可选字段有:code, id, m1
                                                class BB(models.Model):
    
                                                code = models.CharField(max_length=12)
                                                m1 = models.ManyToManyField('self',symmetrical=True)
    
                                            # 可选字段有: bb, code, id, m1
                                                class BB(models.Model):
    
                                                code = models.CharField(max_length=12)
                                                m1 = models.ManyToManyField('self',symmetrical=False)
    
            through=None,               # 自定义第三张表时,使用字段用于指定关系表
            through_fields=None,        # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表
                                            from django.db import models
    
                                            class Person(models.Model):
                                                name = models.CharField(max_length=50)
    
                                            class Group(models.Model):
                                                name = models.CharField(max_length=128)
                                                members = models.ManyToManyField(
                                                    Person,
                                                    through='Membership',
                                                    through_fields=('group', 'person'),
                                                )
    
                                            class Membership(models.Model):
                                                group = models.ForeignKey(Group, on_delete=models.CASCADE)
                                                person = models.ForeignKey(Person, on_delete=models.CASCADE)
                                                inviter = models.ForeignKey(
                                                    Person,
                                                    on_delete=models.CASCADE,
                                                    related_name="membership_invites",
                                                )
                                                invite_reason = models.CharField(max_length=64)
            db_constraint=True,         # 是否在数据库中创建外键约束
            db_table=None,              # 默认创建第三张表时,数据库中表的名称
    View Code
    class UserType(models.Model):
        name = models.CharField(max_length=32)
    
    
    class User(models.Model):
    
        user = models.CharField(max_length=32)
        pwd = models.CharField(max_length=64)
        ut = models.ForeignKey(
            to='UserType',
            to_field='id',
            on_delete=models.CASCADE
            )
    # 正向操作
    v = User.objects.all()
    for item in v:
        item.user
        item.pwd
        item.ut.name
    
    User.objects.all().values('user','ut__name')
    
    # 反向操作
    v = UserType.objects.all()
    for item in v:
        item.name
        item.id
        # 当前类型对应的所有用户的集合
        item.user_set.all()
        
    # 表名__字段  反向查找内容
    UserType.objects.all().values('name','user__pwd')

    如果加上related_name='b',反向查找就会将表名变更为b,如:UserType.objects.all().values('name','b__pwd')

    Ajax:

    参考:https://www.cnblogs.com/wupeiqi/articles/5703697.html

      建议:永远让服务器端返回一个字典,使用return HttpResponse(json.dumps(字典))

      不能用redirect

    悄悄的提交,用Ajax
    
    $.ajax({
        url:"/host",
        type:"POST"
        data:{"k1":123,"k2":"root"}
        success:function(data){
        //函数等服务器返回信息后,自动触发,返回的数据会放到data里,所以需要一个参数
        }
    })
    
    location.reload()         Jqery刷新页面
    location.href = "某个地址"   跳转到其他页面

    $.get(url='xxx',data={})
    $.getJson
    $.post

    不管是哪个方法,都调用了$.ajax方法


    ajax return的时候用HttpResponse()

    js转换json

    var obj = JSON.parse() 字符串转换为其他
    JSON.stringfy() 转换为字符串

     traditional:true      允许发送列表

    dataType:        写上这句,ajax会自动对接从服务器接收到的字符串反序列化

    $(function () {
                    $('#add_submit_ajax').click(function () {
                       $.ajax({
                           url:'/ajax_add_app',
    {#                       data:{'user':123,'host_list':[1,2,3]},#}
                           data:$('#add_form').serialize(),
                           type:"POST",
    {#                       允许发送列表#}
                           traditional:true,
    {#                       写上这句就能让其自动反序列化,所以传递进入函数的就变成了对象#}
                           dataType:"JSON",
                           success:function (obj) {
                                console.log(obj)
                               location.reload()
                           },
    {#                       若是拿去数据不成功的时候执行的函数#}
                           error:function () {
    
                           }
                       })
                    });
    }

     要想知道request对象里面有什么东西,就要知道这个对象是从哪个类生成的,然后查看对应类的函数,如type(request)查出对应类,然后导入查看

     

    {#             若是要用POST方式发送的情况,必须要写上请求头说明发送的方式告知后端如何获取信息 #}
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <input type="button" value="Ajax1" onclick="Ajax1()" />
        
        <script>
            function Ajax1() {
                var xhr = new XMLHttpRequest();
    {#            指定发送方式,以及发送到哪里 true是否异步#}
                xhr.open('GET','/ajax_json/',true);
                xhr.onreadystatechange = function () {
                    if(xhr.readyState = 4){
                        //有四种状态,当readyState等于4的时候就是接收数据完毕状态,显示对应的值
    {#                    console.log(xhr.responseText);#}
                        var obj = JSON.parse(xhr.responseText);
                        console.log(obj);
                    }
                };
    {#            发送请求头#}
                xhr.setRequestHeader('k1','v1');
    {#             若是要用POST方式发送的情况,必须要写上请求头说明发送的方式告知后端如何获取信息 #}
                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
    {#            发送数据#}
                xhr.send("name=root;pwd=123");
            }
        </script>
    </body>
    </html>
    ajax.html
    def ajax_json(request):
        ret = {'status':True,'data':None}
        import json
        return HttpResponse(json.dumps(ret))

    发送文件时机: iframe =》jQuery(依赖FormData),XMLHttpRequest(FormData) 
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .upload{
    {#            position: absolute;#}
                display: inline-block;
                padding: 10px;
                background-color: brown;
                top:0;
                bottom: 0;
                right: 0;
                left:0;
                z-index:90;
            }
            .file{
                position: absolute;
                width: 100px;
                height: 50px;
                opacity: 0;
                top:0;
                bottom: 0;
                right: 0;
                left:0;
                z-index:100;
            }
        </style>
    </head>
    <body>
        <div style="position: relative; 100px;height: 50px;">
            <input class="file" type="file" id="fafa" name="ff" />
            <a class="upload">上传</a>
        </div>
        <input type="button" value=" 提交" onclick="xhrSubmit();" />
        <input type="button" value=" JQ提交" onclick="JQSubmit();" />
    
        <hr>
         <form action="/upload_file/" method="post"target="ifm1" enctype="multipart/form-data">
            {% csrf_token %}
            <iframe id="ifm1" name="ifm1"></iframe>
            <input type="file" name="fafa" />
    
            <input type="submit" onclick="iframeSubmit();" value="Form提交" />
        </form>
    
        <script src="/static/jquery-1.12.4.js"></script>
        <script>
            function JQSubmit() {
    {#            $('#fafa')[0]相当于下面#}
    {#            .files[0];代表要上传的文件对象#}
                var file_obj = document.getElementById('fafa').files[0];
                var fd = new FormData();
                fd.append('fafa',file_obj);
                fd.append('username','root');
    
                $.ajax({
                    url:'/upload_file/',
                    type:'POST',
                    data:fd,
    {#                processData:false, contentType:false,表名上传文件的时候不要做特殊处理,这样才能正确传递文件#}
                    processData:false,
                    contentType:false,
                    sucess:function (arg,a1,a2) {
                        console.log(arg);
                        console.log(a1);
                        console.log(a2);
                    }
                })
            }
             function xhrSubmit() {
    {#            $('#fafa')[0]相当于下面#}
    {#            .files[0];代表要上传的文件对象#}
                var file_obj = document.getElementById('fafa').files[0];
                var fd = new FormData();
                fd.append('fafa',file_obj);
                fd.append('username','root');
    
                var xhr = new XMLHttpRequest();
                xhr.open('POST','/upload_file/',true);
                xhr.onreadystatechange = function () {
                    if(xhr.readyState = 4){
                        var obj = Json.parse(xhr.responseText);
                    }
                };
                xhr.send(fd);
            }
    {#       前面两种方法都存在浏览器兼容问题,而这个 iframe提交文件,兼容性强#}
             function iframeSubmit() {
                $('#ifm1').load(function () {
    {#                iframe比较特殊,需要先用$('#ifm1').contents()找到下面对应的HTML,然后找里面body的内容#}
                    var text = $('#ifm1').contents().find('body').text();
                    var obj = JSON.parse(text);
                })
            }
    
        </script>
    </body>
    </html>
    上传文件三种方式,iframe上传兼容性比较强
    
    

    增加了预览图片,以及选中文件就上传

    
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .upload{
    {#            position: absolute;#}
                display: inline-block;
                padding: 10px;
                background-color: brown;
                top:0;
                bottom: 0;
                right: 0;
                left:0;
                z-index:90;
            }
            .file{
                position: absolute;
                width: 100px;
                height: 50px;
                opacity: 0;
                top:0;
                bottom: 0;
                right: 0;
                left:0;
                z-index:100;
            }
        </style>
    </head>
    <body>
        <div style="position: relative; 100px;height: 50px;">
            <input class="file" type="file" id="fafa" name="ff" />
            <a class="upload">上传</a>
        </div>
        <input type="button" value=" 提交" onclick="xhrSubmit();" />
        <input type="button" value=" JQ提交" onclick="JQSubmit();" />
    
        <hr>
         <form id="fm1" action="/upload_file/" method="post"target="ifm1" enctype="multipart/form-data">
            {% csrf_token %}
            <iframe id="ifm1" name="ifm1" style="display: none"></iframe>
            <input type="file" name="fafa" onchange="changeUpload();"/>
    
            <input type="submit" onclick="iframeSubmit();" value="Form提交" />
        </form>
    
    
        <div id="preview">
    
        </div>
    
    
    
        <script src="/static/jquery-1.12.4.js"></script>
        <script>
            function changeUpload() {
                {#            让form表单改变就提交#}
                $('#ifm1').load(function () {
    {#                iframe比较特殊,需要先用$('#ifm1').contents()找到下面对应的HTML,然后找里面body的内容#}
                    var text = $('#ifm1').contents().find('body').text();
                    var obj = JSON.parse(text);
    
    {#                将原来的图片清空了,才能显示新图片#}
                    $('#preview').empty();
    {#                建立图片标签#}
                    var imgTag = document.createElement('img');
    {#                因为服务器传递过来的数据是没有前面的/,所以需要加上#}
                    imgTag.src='/'+obj.data;
                    $('#preview').append(imgTag);
    
                });
    
                $('#fm1').submit();
            }
            
            function JQSubmit() {
    {#            $('#fafa')[0]相当于下面#}
    {#            .files[0];代表要上传的文件对象#}
                var file_obj = document.getElementById('fafa').files[0];
                var fd = new FormData();
                fd.append('fafa',file_obj);
                fd.append('username','root');
    
                $.ajax({
                    url:'/upload_file/',
                    type:'POST',
                    data:fd,
    {#                processData:false, contentType:false,表名上传文件的时候不要做特殊处理,这样才能正确传递文件#}
                    processData:false,
                    contentType:false,
                    sucess:function (arg,a1,a2) {
                        console.log(arg);
                        console.log(a1);
                        console.log(a2);
                    }
                })
            }
             function xhrSubmit() {
    {#            $('#fafa')[0]相当于下面#}
    {#            .files[0];代表要上传的文件对象#}
                var file_obj = document.getElementById('fafa').files[0];
                var fd = new FormData();
                fd.append('fafa',file_obj);
                fd.append('username','root');
    
                var xhr = new XMLHttpRequest();
                xhr.open('POST','/upload_file/',true);
                xhr.onreadystatechange = function () {
                    if(xhr.readyState = 4){
                        var obj = Json.parse(xhr.responseText);
                    }
                };
                xhr.send(fd);
            }
    {#       前面两种方法都存在浏览器兼容问题,而这个 iframe提交文件,兼容性强#}
             function iframeSubmit() {
                $('#ifm1').load(function () {
    {#                iframe比较特殊,需要先用$('#ifm1').contents()找到下面对应的HTML,然后找里面body的内容#}
                    var text = $('#ifm1').contents().find('body').text();
                    var obj = JSON.parse(text);
    
    {#                将原来的图片清空了,才能显示新图片#}
                    $('#preview').empty();
    {#                建立图片标签#}
                    var imgTag = document.createElement('img');
    {#                因为服务器传递过来的数据是没有前面的/,所以需要加上#}
                    imgTag.src='/'+obj.data;
                    $('#preview').append(imgTag);
    
                })
            }
    
        </script>
    </body>
    </html>
    优化了的上传文件
    
    
    
    from django.shortcuts import render,HttpResponse
    from django import forms
    from django.forms import fields
    from django.forms import fields as Ffields
    from app01 import models
    # Create your views here.
    
    # 避免跟modelform的属性冲突,更名为Fwidgets
    from django.forms import widgets as Fwidgets
    # # modelform方式
    class UserInfoModelForm(forms.ModelForm):
    
        # 自定义字段,跟保存在数据库上没关系,例如一个月内免登陆的CheckBox
        is_rmb = Ffields.CharField(     widget=Fwidgets.CheckboxInput() )
    
        class Meta:
            # 这里指定字段对应的表
            model  =models.UserInfo
            # __all__代表多有的字段
            fields = '__all__'
    
            # 只显示的字段
            # fields = ['username','email']
            # 排除字段,其他的显示
            # exclude = ['email']
            # 显示标签更名
            labels = {
                'username':'用户名',
                'email':'邮箱'
            }
            #
            help_texts = {
                'username':'帮助信息'
            }
            # 将原来的CharField改为为Textarea
            widgets = {
                'username':Fwidgets.Textarea(attrs={'class':'c1'})
            }
            error_messages = {
                '__all__':'所有字段共同的错误',
                # email的错误信息
                'email':{
                    'required':'邮箱不能为空',
                    'invalid':'邮箱格式错误'
    
                }
            }
            # 更改格式,
            # field_classes = {
            #     # 将email的格式从邮箱给为url格式,这里是填写类,不是带括号的对象
            #     'email': Ffields.URLField
            # }
    
    # form方式
    class UserInfoForm(forms.Form):
        # 定义字段
        username = fields.CharField(max_length=32,label='用户名')
        email = fields.EmailField(label='邮件')
        # 将数据库的id caption字段作为下拉显示
        user_type = fields.ChoiceField(
            choices = models.UserType.objects.values_list('id','caption'),
            label='类型'
        )
        def __init__(self,*args,**kwargs):
            super(UserInfoForm,self).__init__(*args,**kwargs)
            # 这样子就能更新数据库不需要重启程序就能更新数据
            self.fields['user_type'].choices = models.UserType.objects.values_list('id','caption')
    
    def index(request):
    
        if request.method == 'GET':
    
            # 创建对象,会在前段自动生成对应的标签
            obj = UserInfoModelForm()
    
            return render(request,'index.html',{'obj':obj})
            # return render(request,'index.html')
        elif request.method == 'POST':
            # 创建对象,会在前段自动生成对应的标签
            obj = UserInfoModelForm(request.POST)
            if obj.is_valid():
                # obj.save()
                # 上面一句包含了下面三句代码,只不过默认传入commit=True
                instance = obj.save(False)
                instance.save()
                obj.save_m2m()
            # print(obj.is_valid())
            # print(obj.cleaned_data)
            # print(obj.errors)
            # obj.cleaned_data
    
            return render(request, 'index.html', {'obj': obj})
    
    
    
    def user_list(request):
    
        li = models.UserInfo.objects.all().select_related('user_type')
        return render(request,'user_list.html',{'li':li})
    
    
    def user_edit(request,nid):
        # 获取当前id对象的用户信息
        # 显示用户已经存在的数据
        if request.method == "GET":
            user_obj = models.UserInfo.objects.filter(id=nid).first()
            mf = UserInfoModelForm(instance=user_obj)
            return render(request,'user_edit.html',{'mf':mf,'nid':nid})
        elif request.method == 'POST':
            user_obj = models.UserInfo.objects.filter(id=nid).first()
            # instance=user_obj)告诉数据库要更新的是哪个对象
            mf = UserInfoModelForm(request.POST,instance=user_obj)
            if mf.is_valid():
                mf.save()
    
            else:
                print(mf.errors.as_json())
            return render(request, 'user_edit.html', {'mf': mf, 'nid': nid})
    
    def ajax(request):
        return render(request,'ajax.html')
    
    
    def ajax_json(request):
        ret = {'status':True,'data':request.POST.get('username')}
        import json
        return HttpResponse(json.dumps(ret))
    
    
    def upload(request):
        return render(request,'upload.html')
    
    def upload_file(request):
    
        username = request.POST.get('username')
        fafa = request.FILES.get('fafa')
        import os
        img_path = os.path.join('static','imgs',fafa.name)
        print(img_path)
        # img_path = fafa.name
    
        with open(img_path,'wb') as f:
            for item in fafa.chunks():
                f.write(item)
        ret = {'code':True,'data':img_path}
    
        print(username,fafa)
        import json
        return HttpResponse(json.dumps(ret))
    views.py

    session+验证码图片

    1.创建一张图片

    2.在图片中写入随机字符串

    3.将图片写入到指定文件中

    4.打开制定目录文件,读取内容

    5.HTTPResponse(data)

    需要用到session,check_code.py(依赖:Pillow,字体文件),点一次就变化的话,需要src属性后面加?




    HTML模板继承

    注意:只能继承一个模板

    头顶要写上继续哪个模板 {% extends '模板名 %}

     {% extends 'master.html' %}

     被继承的模板写成:{% block 模板名%}  {% endblock %}

    {% block content %} {% endblock %}

    继承的模板写成  (block模块位置是没所谓的)
    {% block 模板名%} 替换的内容 {% endblock %}

     

     模板的导入(导入可以导入多个模板)

    {% include '模板名' %}
    {% include 'tag.html' %}
    <form>
        <input type="text" />
        <input type="submit" />
    </form>
    tag.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
        {% include 'tag.html' %}
        {% include 'tag.html' %}
    
    </body>
    </html>
    index.html
    django自带的方法:  
    帮助方法:
    {{ item.event_start|date:"Y-m-d H:i:s"}} 
    {{ bio|truncatewords:"30" }}         # 获取前30个字符,进行分割
    {{ my_list|first|upper }}           # 第一个字符转换为大写
    {{ name|lower }}                #转换为小写
    
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    <p></p>
        {{ name }}
    <div></div>
        {{ name | lower }}
    </body>
    </html>
    例子

    自定义simple_tag

      优点:参数任意

      缺点:不能作为if条件

      1.在某个APP目录下创建一个目录templatetags(必须是这个名字)

      2.templatetags目录下创建.py文件

      3.创建template对象 必须为register  请参考下面代码

      

    from django import template
    from django.utils.safestring import mark_safe
    
    # 装饰器,名字不能修改,必须为register
    register  = template.Library()
    
    @register.simple_tag
    def houyafan(a1,a2):
        return a1 + a2
    xxoo.py

      4.settings注册app

     

       5.HTML文件顶部写上{% load py文件名 %}:  {% load xxoo %}

       6.{% 函数名 参数a1 参数a2 %}  {% houyafan 2 5 %}

    自定义simple_filter

    优点:能作为if条件

    缺点:参数任意,不能加空格

    步骤与simple_tag一样,

     写法:

    {{ '参数1'|函数名:'参数2,参数三' }}
    {{ '字符串'|filter_test:'相加,参数三' }}
    from django import template
    from django.utils.safestring import mark_safe
    
    # 装饰器,名字不能修改,必须为register
    register  = template.Library()
    
    # filter最多传递两个值
    @register.filter
    def filter_test(a1,a2):
        return a1 + a2
    View Code
    {% load xxoo %}
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        {% houyafan 2 5 %}
    {#    不能加空格#}
         {{ '字符串'|filter_test:'相加' }}
    {#    如果需要传递三个以上参数,只能这样弄#}
    {#    这种方式一般用于if else里面#}
         {{ '字符串'|filter_test:'相加,参数三' }}
    
        {%  if '字符串'|filter_test:'相加' %}
            显示
        {% endif %}
    
    
    {#    {% include 'tag.html' %}#}
    {#    {% include 'tag.html' %}#}
    {#<p></p>#}
    {#    {{ name }}#}
    {#<div></div>#}
    {#    {{ name | lower }}#}
    </body>
    </html>
    index.html

    分页

    XSS攻击:默认传递带有HTML语言的字符串是不安全的,不会做解析
    后端需要加上
    from django.utils.safestring import mark_safe
    page_str='''<a href="/user_list/?p=2">1 </a>'''
    page_str = mark_safe(page_str)

    前端需要这样写

    {{ page_str|safe }}

    from django.shortcuts import render,HttpResponse
    from django.shortcuts import redirect
    from django.utils.safestring import mark_safe
    
    from app01 import models
    import json
    # Create your views here.
    
    def business(request):
    
        # 获取数据,保存为queryset列表
        v = models.Business.objects.all()
    
        # 查找特定的列,类似select id,caption from business,返回的是字典
        v2 = models.Business.objects.all().values('id','caption')
    
        # 查询获取的结果,返回的是元组
        v3 = models.Business.objects.all().values_list('id','caption')
    
    
        return render(request,'business.html',{'v':v,"v2":v2,"v3":v3})
    
    
    def host(request):
        if request.method == "GET":
            v = models.Business.objects.filter(host__nid__gt=0)
            # # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为字典类型
            # v2 = models.Business.objects.all().values('nid', 'hostname', 'b__id', 'b__caption')
            # print(type(v2))
            # for row in v2:
            #     print(row['nid'], row['hostname'], row['b_id'], row['b__caption'])
    
            # # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为元组,下标安装下方的写的参数从0排序+1
            # v3 = models.Business.objects.all().values_list('nid', 'hostname', 'b_id', 'b__caption')
            # print(type(v3))
    
            b_list = models.Host.objects.all()
            for row in b_list:
                print(row.hostname)
    
            return render(request, 'host.html', {"v": v,'b_list':b_list})
        # return render(request,'host.html',{"v":v,"v2":v2,"v3":v3})
    
        elif request.method == 'POST':
            h = request.POST.get('hostname')
            i = request.POST.get('ip')
            p = request.POST.get('port')
            b = request.POST.get('b_id')
            print(h)
            print(i)
            print(p)
            print(b)
    
            models.Host.objects.create(hostname = h,
                                       ip = i,
                                       port = p,
                                       b_id = b
                                       )
    
            return redirect('/host/')
    
    
    def test_ajax(request):
        # request.GET.get('pwd',sep='	')获取pwd的值,并且隔开
        # print(request.method,request.GET.get('user'),request.GET.get('pwd',sep='	'))
    
        ret = {'status': True, 'error': None, 'data': None}
        try:
    
            h = request.POST.get('hostname')
            i = request.POST.get('ip')
            p = request.POST.get('port')
            b = request.POST.get('b_id')
            print(h)
            print(i)
            print(p)
            print(b)
            if h and len(h) > 5:
                models.Host.objects.create(hostname=h,
                                           ip=i,
                                           port=p,
                                           b_id=b
                                           )
    
            else:
                ret['status'] = False
                ret['error'] = '太短了'
    
    
        except Exception as e:
            ret['status'] = False
            ret['error'] = '请求错误'
        return HttpResponse(json.dumps(ret))
    
    
    def app(request):
        if request.method == 'GET':
            app_list = models.Application.objects.all()
            for row in app_list:
                print(row.name,row.r.all())
    
            host_list = models.Host.objects.all()
            return render(request,'app.html',{'app_list':app_list,'host_list':host_list})
        elif request.method == 'POST':
            app_name = request.POST.get('app_name')
            host_list = request.POST.getlist('host_list')
            print(app_name,host_list)
    
            obj = models.Application.objects.create(name = app_name)
            obj.r.add(*host_list)
    
            return redirect('/app/')
    
    def ajax_add_app(request):
        ret = {'status':True,'error':None,"data":None}
        app_name = request.POST.get('app_name')
        host_list =request.POST.getlist('host_list')
        obj = models.Application.objects.create(name=app_name)
        obj.r.add(*host_list)
    
    
    
        return HttpResponse(json.dumps(ret))
    
    
    def index(request):
        name = 'QWERTYU'
        return render(request,'index.html',{'name':name})
    
    LIST = []
    for i in range(109):
        LIST.append(i)
    
    def user_list(request):
        #  当前页,获取p的值,若没有值的时候,默认为1
        current_page = request.GET.get('p',1)
        # 传递过来的是字符串,这边是数字计算的
        current_page = int(current_page)
        start = (current_page-1) * 10
        end = current_page * 10
    
        li = LIST[start:end]
    
        all_count = len(LIST)
        # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
        count,y = divmod(all_count,10)
        # 如果有余数,分页数需要+1
        if y:
            count +=1
    
        page_list = []
        for i in range(1,count+1):
            # 如果i等于当前页。将当前页颜色变一下
            if i == current_page:
                temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
            else:
                temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
            page_list.append(temp)
    
        page_str = " ".join(page_list)
        page_str = mark_safe(page_str)
    
        return render(request,'user_list.html',{'li':li,'page_str':page_str})
    views.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .pagenation .page{
                display: inline-block;
                padding: 5px;
                background-color: grey;
                margin: 5px;
            }
             .pagenation .page.active{
                 background-color: brown;
                 color: white;
             }
        </style>
    </head>
    <body>
        <ul>
            {% for item in li %}
               {% include 'li.html' %}
            {% endfor %}
        </ul>
        <div class="pagenation">
            {{ page_str }}
        </div>
    
    
    
    </body>
    </html>
    user_list.html
    """day20 URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/2.0/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  path('', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.urls import include, path
        2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
    """
    from django.contrib import admin
    from django.urls import path
    
    from django.conf.urls import url
    from app01 import views
    urlpatterns = [
    
        url(r'^user_list/$', views.user_list),
    
    ]
    urls.py
    from django.shortcuts import render,HttpResponse
    from django.shortcuts import redirect
    from django.utils.safestring import mark_safe
    
    from app01 import models
    import json
    # Create your views here.
    
    def business(request):
    
        # 获取数据,保存为queryset列表
        v = models.Business.objects.all()
    
        # 查找特定的列,类似select id,caption from business,返回的是字典
        v2 = models.Business.objects.all().values('id','caption')
    
        # 查询获取的结果,返回的是元组
        v3 = models.Business.objects.all().values_list('id','caption')
    
    
        return render(request,'business.html',{'v':v,"v2":v2,"v3":v3})
    
    
    def host(request):
        if request.method == "GET":
            v = models.Business.objects.filter(host__nid__gt=0)
            # # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为字典类型
            # v2 = models.Business.objects.all().values('nid', 'hostname', 'b__id', 'b__caption')
            # print(type(v2))
            # for row in v2:
            #     print(row['nid'], row['hostname'], row['b_id'], row['b__caption'])
    
            # # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为元组,下标安装下方的写的参数从0排序+1
            # v3 = models.Business.objects.all().values_list('nid', 'hostname', 'b_id', 'b__caption')
            # print(type(v3))
    
            b_list = models.Host.objects.all()
            for row in b_list:
                print(row.hostname)
    
            return render(request, 'host.html', {"v": v,'b_list':b_list})
        # return render(request,'host.html',{"v":v,"v2":v2,"v3":v3})
    
        elif request.method == 'POST':
            h = request.POST.get('hostname')
            i = request.POST.get('ip')
            p = request.POST.get('port')
            b = request.POST.get('b_id')
            print(h)
            print(i)
            print(p)
            print(b)
    
            models.Host.objects.create(hostname = h,
                                       ip = i,
                                       port = p,
                                       b_id = b
                                       )
    
            return redirect('/host/')
    
    
    def test_ajax(request):
        # request.GET.get('pwd',sep='	')获取pwd的值,并且隔开
        # print(request.method,request.GET.get('user'),request.GET.get('pwd',sep='	'))
    
        ret = {'status': True, 'error': None, 'data': None}
        try:
    
            h = request.POST.get('hostname')
            i = request.POST.get('ip')
            p = request.POST.get('port')
            b = request.POST.get('b_id')
            print(h)
            print(i)
            print(p)
            print(b)
            if h and len(h) > 5:
                models.Host.objects.create(hostname=h,
                                           ip=i,
                                           port=p,
                                           b_id=b
                                           )
    
            else:
                ret['status'] = False
                ret['error'] = '太短了'
    
    
        except Exception as e:
            ret['status'] = False
            ret['error'] = '请求错误'
        return HttpResponse(json.dumps(ret))
    
    
    def app(request):
        if request.method == 'GET':
            app_list = models.Application.objects.all()
            for row in app_list:
                print(row.name,row.r.all())
    
            host_list = models.Host.objects.all()
            return render(request,'app.html',{'app_list':app_list,'host_list':host_list})
        elif request.method == 'POST':
            app_name = request.POST.get('app_name')
            host_list = request.POST.getlist('host_list')
            print(app_name,host_list)
    
            obj = models.Application.objects.create(name = app_name)
            obj.r.add(*host_list)
    
            return redirect('/app/')
    
    def ajax_add_app(request):
        ret = {'status':True,'error':None,"data":None}
        app_name = request.POST.get('app_name')
        host_list =request.POST.getlist('host_list')
        obj = models.Application.objects.create(name=app_name)
        obj.r.add(*host_list)
    
    
    
        return HttpResponse(json.dumps(ret))
    
    
    def index(request):
        name = 'QWERTYU'
        return render(request,'index.html',{'name':name})
    
    LIST = []
    for i in range(500):
        LIST.append(i)
    
    # def user_list(request):
    #     #  当前页,获取p的值,若没有值的时候,默认为1
    #     current_page = request.GET.get('p',1)
    #     # 传递过来的是字符串,这边是数字计算的
    #     current_page = int(current_page)
    #     start = (current_page-1) * 10
    #     end = current_page * 10
    #
    #     li = LIST[start:end]
    #
    #     all_count = len(LIST)
    #     # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
    #     count,y = divmod(all_count,10)
    #     # 如果有余数,分页数需要+1
    #     if y:
    #         count +=1
    #
    #     page_list = []
    #     for i in range(1,count+1):
    #         # 如果i等于当前页。将当前页颜色变一下
    #         if i == current_page:
    #             temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
    #         else:
    #             temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
    #         page_list.append(temp)
    #
    #     page_str = " ".join(page_list)
    #     page_str = mark_safe(page_str)
    #
    #     return render(request,'user_list.html',{'li':li,'page_str':page_str})
    def user_list(request):
        #  当前页,获取p的值,若没有值的时候,默认为1
        current_page = request.GET.get('p',1)
        # 传递过来的是字符串,这边是数字计算的
        current_page = int(current_page)
        start = (current_page-1) * 10
        end = current_page * 10
    
        li = LIST[start:end]
    
        all_count = len(LIST)
        # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
        total_count,y = divmod(all_count,10)
        # 如果有余数,分页数需要+1
        if y:
            total_count +=1
    
        page_list = []
        # 显示页面当前页的前后五页
        # start_index = current_page - 5
        # end_index = current_page + 5 +1
        if total_count < 11:
            start_index = 0
            end_index = total_count
    
        else:
            if current_page <= 6 :
                start_index = 1
                end_index = 11
            else:
                start_index = current_page - 5
                end_index = current_page +5 +1
                if (current_page + 5) > total_count:
                    start_index  = total_count - 11 +1
                    end_index = total_count +1
    
    
        for i in range(start_index,end_index):
            # 如果i等于当前页。将当前页颜色变一下
            if i == current_page:
                temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
            else:
                temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
            page_list.append(temp)
    
        page_str = " ".join(page_list)
        page_str = mark_safe(page_str)
    
        return render(request,'user_list.html',{'li':li,'page_str':page_str})
    优化版,11
    from django.shortcuts import render,HttpResponse
    from django.shortcuts import redirect
    from django.utils.safestring import mark_safe
    
    from app01 import models
    import json
    # Create your views here.
    
    def business(request):
    
        # 获取数据,保存为queryset列表
        v = models.Business.objects.all()
    
        # 查找特定的列,类似select id,caption from business,返回的是字典
        v2 = models.Business.objects.all().values('id','caption')
    
        # 查询获取的结果,返回的是元组
        v3 = models.Business.objects.all().values_list('id','caption')
    
    
        return render(request,'business.html',{'v':v,"v2":v2,"v3":v3})
    
    
    def host(request):
        if request.method == "GET":
            v = models.Business.objects.filter(host__nid__gt=0)
            # # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为字典类型
            # v2 = models.Business.objects.all().values('nid', 'hostname', 'b__id', 'b__caption')
            # print(type(v2))
            # for row in v2:
            #     print(row['nid'], row['hostname'], row['b_id'], row['b__caption'])
    
            # # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为元组,下标安装下方的写的参数从0排序+1
            # v3 = models.Business.objects.all().values_list('nid', 'hostname', 'b_id', 'b__caption')
            # print(type(v3))
    
            b_list = models.Host.objects.all()
            for row in b_list:
                print(row.hostname)
    
            return render(request, 'host.html', {"v": v,'b_list':b_list})
        # return render(request,'host.html',{"v":v,"v2":v2,"v3":v3})
    
        elif request.method == 'POST':
            h = request.POST.get('hostname')
            i = request.POST.get('ip')
            p = request.POST.get('port')
            b = request.POST.get('b_id')
            print(h)
            print(i)
            print(p)
            print(b)
    
            models.Host.objects.create(hostname = h,
                                       ip = i,
                                       port = p,
                                       b_id = b
                                       )
    
            return redirect('/host/')
    
    
    def test_ajax(request):
        # request.GET.get('pwd',sep='	')获取pwd的值,并且隔开
        # print(request.method,request.GET.get('user'),request.GET.get('pwd',sep='	'))
    
        ret = {'status': True, 'error': None, 'data': None}
        try:
    
            h = request.POST.get('hostname')
            i = request.POST.get('ip')
            p = request.POST.get('port')
            b = request.POST.get('b_id')
            print(h)
            print(i)
            print(p)
            print(b)
            if h and len(h) > 5:
                models.Host.objects.create(hostname=h,
                                           ip=i,
                                           port=p,
                                           b_id=b
                                           )
    
            else:
                ret['status'] = False
                ret['error'] = '太短了'
    
    
        except Exception as e:
            ret['status'] = False
            ret['error'] = '请求错误'
        return HttpResponse(json.dumps(ret))
    
    
    def app(request):
        if request.method == 'GET':
            app_list = models.Application.objects.all()
            for row in app_list:
                print(row.name,row.r.all())
    
            host_list = models.Host.objects.all()
            return render(request,'app.html',{'app_list':app_list,'host_list':host_list})
        elif request.method == 'POST':
            app_name = request.POST.get('app_name')
            host_list = request.POST.getlist('host_list')
            print(app_name,host_list)
    
            obj = models.Application.objects.create(name = app_name)
            obj.r.add(*host_list)
    
            return redirect('/app/')
    
    def ajax_add_app(request):
        ret = {'status':True,'error':None,"data":None}
        app_name = request.POST.get('app_name')
        host_list =request.POST.getlist('host_list')
        obj = models.Application.objects.create(name=app_name)
        obj.r.add(*host_list)
    
    
    
        return HttpResponse(json.dumps(ret))
    
    
    def index(request):
        name = 'QWERTYU'
        return render(request,'index.html',{'name':name})
    
    LIST = []
    for i in range(500):
        LIST.append(i)
    
    # def user_list(request):
    #     #  当前页,获取p的值,若没有值的时候,默认为1
    #     current_page = request.GET.get('p',1)
    #     # 传递过来的是字符串,这边是数字计算的
    #     current_page = int(current_page)
    #     start = (current_page-1) * 10
    #     end = current_page * 10
    #
    #     li = LIST[start:end]
    #
    #     all_count = len(LIST)
    #     # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
    #     count,y = divmod(all_count,10)
    #     # 如果有余数,分页数需要+1
    #     if y:
    #         count +=1
    #
    #     page_list = []
    #     for i in range(1,count+1):
    #         # 如果i等于当前页。将当前页颜色变一下
    #         if i == current_page:
    #             temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
    #         else:
    #             temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
    #         page_list.append(temp)
    #
    #     page_str = " ".join(page_list)
    #     page_str = mark_safe(page_str)
    #
    #     return render(request,'user_list.html',{'li':li,'page_str':page_str})
    # def user_list(request):
    #     '''
    #     特定为10页的时候
    #     :param request:
    #     :return:
    #     '''
    #     #  当前页,获取p的值,若没有值的时候,默认为1
    #     current_page = request.GET.get('p',1)
    #     # 传递过来的是字符串,这边是数字计算的
    #     current_page = int(current_page)
    #     start = (current_page-1) * 10
    #     end = current_page * 10
    #
    #     li = LIST[start:end]
    #
    #     all_count = len(LIST)
    #     # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
    #     total_count,y = divmod(all_count,10)
    #     # 如果有余数,分页数需要+1
    #     if y:
    #         total_count +=1
    #
    #     page_list = []
    #     # 显示页面当前页的前后五页
    #     # start_index = current_page - 5
    #     # end_index = current_page + 5 +1
    #     if total_count < 11:
    #         start_index = 0
    #         end_index = total_count
    #
    #     else:
    #         if current_page <= 6 :
    #             start_index = 1
    #             end_index = 11
    #         else:
    #             start_index = current_page - 5
    #             end_index = current_page +5 +1
    #             if (current_page + 5) > total_count:
    #                 start_index  = total_count - 11 +1
    #                 end_index = total_count +1
    #
    #
    #     for i in range(start_index,end_index):
    #         # 如果i等于当前页。将当前页颜色变一下
    #         if i == current_page:
    #             temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
    #         else:
    #             temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
    #         page_list.append(temp)
    #
    #     page_str = " ".join(page_list)
    #     page_str = mark_safe(page_str)
    #
    #     return render(request,'user_list.html',{'li':li,'page_str':page_str})
    def user_list(request):
        '''
    
        :param request:
        :return:
        '''
        #  当前页,获取p的值,若没有值的时候,默认为1
        current_page = request.GET.get('p',1)
        # 传递过来的是字符串,这边是数字计算的
        current_page = int(current_page)
        start = (current_page-1) * 10
        end = current_page * 10
    
        li = LIST[start:end]
    
        all_count = len(LIST)
        # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
        total_count,y = divmod(all_count,10)
        # 如果有余数,分页数需要+1
        if y:
            total_count +=1
    
        page_list = []
        # 显示页码多少个,这里是11,建议使用基数
        perpage_num = 11
        # 显示页面当前页的前后五页
        # start_index = current_page - 5
        # end_index = current_page + 5 +1
        if total_count < perpage_num:
            start_index = 0
            end_index = total_count
    
        else:
            if current_page <= (perpage_num+1)/2 :
                start_index = 1
                end_index = perpage_num
            else:
                start_index = current_page - (perpage_num-1)/2
                end_index = current_page +(perpage_num-1)/2 +1
                if (current_page + (perpage_num-1)/2) > total_count:
                    start_index  = total_count - perpage_num +1
                    end_index = total_count +1
        if current_page ==1:
            # javascript:void(0);这个代表什么都不干
            prev = '<a class="page active"  href="javascript:void(0);">上一页</a>'
        else:
            prev = '<a class="page active"  href="/user_list/?p=%s">上一页</a>' %(current_page-1)
        page_list.append(prev)
    
        for i in range(int(start_index),int(end_index)):
            # 如果i等于当前页。将当前页颜色变一下
            if i == current_page:
                temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
            else:
                temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
            page_list.append(temp)
        if current_page == total_count:
            nex = '<a class="page active"  href="javascript:void(0)">下一页</a>'
        else:
            nex = '<a class="page active"  href="/user_list/?p=%s">下一页</a>' % (current_page + 1)
        page_list.append(nex)
        # 跳转
        jump = '''
        <input type = 'text'/><a onclick='jumpTo(this,"/user_list/?p=");'id='ii1'>GO</a>
        <script>
            function jumpTo(ths,base){
                var val = ths.previousSibling.value;
                location.href = base + val;
            }
        </script>
        
        '''
        page_list.append(jump)
    
        page_str = " ".join(page_list)
        page_str = mark_safe(page_str)
    
        return render(request,'user_list.html',{'li':li,'page_str':page_str})
    优化版——多了上一页、下一页,跳转
    from django.utils.safestring import mark_safe
    
    class Page:
        def __init__(self,current_page,data_count,per_page_count = 10, pager_num = 7):
            '''
    
            :param current_page: 当前页
            :param data_count: 分页总数
            :param per_page_count: 每一页显示多少行,这里默认10行
            :param pager_num: 分页显示多少页,这里默认7页
            '''
            self.current_page = current_page
            self.data_count = data_count
            self.per_page_count = per_page_count
            self.pager_num = pager_num
        # @property意思是将方法变成属性,不再需要写括号
        @property
        def start(self):
            '''
            分割总行数的开始
            :return:
            '''
            return (self.current_page - 1) * self.per_page_count
        @property
        def end(self):
            '''
            分割总行数的结束
            :return:
            '''
            return self.current_page * self.per_page_count
        @property
        def total_count(self):
            '''
            计算分页页数
            :return:
            '''
            # divmod是将data_count除以per_page_count,计算出值余多少,值传入v,余数传入y
            v,y = divmod(self.data_count,self.per_page_count)
            # 如果有余数,需要增加一页分页
            if y:
                v +=1
            return v
    
        def page_str(self,base_url):
            '''
    
            :param base_url:跳转的地址
            :return:
            '''
            # 传递到前端的列表,用于保存数据
            page_list = []
            # 如果分页总数少于默认的7页,就显示所有分页
            if self.total_count < self.per_page_count:
                start_index = 1
                end_index = self.total_count + 1
    
            else:
                # 如果当前页在显示分页数的一半内
                if self.current_page <= (self.pager_num + 1)/2:
                    start_index = 1
                    end_index = self.pager_num + 1
    
                else:
                    start_index = self.current_page - (self.pager_num -1)/2
                    end_index = self.current_page + (self.pager_num + 1)/2
                    # 处理最后的分页,如果当前页+默认显示页的一半大于总分页数,不会再向后增加页数
                    if (self.current_page + (self.pager_num -1)/2) > self.total_count:
                        start_index = self.total_count - self.pager_num +1
                        end_index = self.total_count +1
    
            # 当前页是第一页的情况,上一页失效
            if self.current_page == 1:
                prev = '<a class="page"  href="javascript:void(0);">上一页</a>'
            else:
                prev = '<a class="page"   href="%s?p=%s">上一页</a>' %(base_url,self.current_page-1)
            page_list.append(prev)
    
            for i in range(int(start_index),int(end_index)):
                # 当前页显示的分页样式不一样
                if i == self.current_page:
                    temp = '<a class="page active"  href="%s?p=%s">%s</a>' % (base_url, i,i)
    
                else:
                    temp = '<a class="page"  href="%s?p=%s">%s</a>' % (base_url, i,i)
    
                page_list.append(temp)
    
            if self.current_page == self.total_count:
                nex = '<a class="page"  href="javascript:void(0);">下一页</a>'
            else:
                nex = '<a class="page"   href="%s?p=%s">下一页</a>' %(base_url,self.current_page+1)
    
            page_list.append(nex)
    
            jump = '''
            <input type = 'text'/><a onclick='jumpTo(this,"%s?p=");'id='ii1'>GO</a>
            <script>
                function jumpTo(ths,base){
                    var val = ths.previousSibling.value;
                    location.href = base + val;
                }
            </script>
    
            '''%(base_url)
            page_list.append(jump)
    
            page_str = mark_safe(" ".join(page_list))
            return page_str
    pagination(分页)
    LIST = []
    for i in range(500)
        LIST.append(i)
    def user_list(request):
        current_age = request.GET.get('p',1)
        current_age = int(current_age)
        page_obj = Page(current_age,len(LIST))
        data = LIST[page_obj.start,page_obj.end]
        page_str = page_obj.page_str('/user_list/')
        return render(request,'user_list.html',{'li':data,'page_str':page_str})
    views.py

    cookie

     客户端浏览器上的一个文件

    cookie的简单应用

    res = redirect('/index/')
    # 设定cookie user 为u
    res.set_cookie('user111',u)    #res.set_cookie('key','value'),默认情况下,关闭浏览器cookie就失效
    # 获取当前已经登陆的用户信息
    v = request.COOKIES.get('user111')

    rep = HttpResponse(...) 或 rep = render(request, ...)
     
    rep.set_cookie(key,value,...)
    rep.set_signed_cookie(key,value,salt='加密盐',...)
        参数:
            key,              键
            value='',         值
            max_age=None,     超时时间,秒多少秒之后失效
            expires=None,     超时时间(IE requires expires, so set it if hasn't been already.)指定某个时间超时
            path='/',         Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问
            domain=None,      Cookie生效的域名
            secure=False,     https传输
            httponly=False    只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

     

      引入jquery的cookie插件
      <script src="/static/jquery-1.12.4.js"></script>

    {# 必须在引入jQuery后面写 #}
    <script src="/static/jquery.cookie.js"></script>

      就能使用$.cookie()
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .pagenation .page{
                display: inline-block;
                padding: 5px;
                background-color: grey;
                margin: 5px;
            }
             .pagenation .page.active{
                 background-color: brown;
                 color: white;
             }
        </style>
    </head>
    <body>
        <ul>
            {% for item in li %}
               {% include 'li.html' %}
            {% endfor %}
        </ul>
        <div>
            <select id="s1" onchange="changePageSize(this)">
                <option value="10">10</option>
                <option value="30">30</option>
                <option value="50">50</option>
                <option value="100">100</option>
            </select>
        </div>
        <div class="pagenation">
            {{ page_str }}
        </div>
        <script src="/static/jquery-1.12.4.js"></script>
    {#    必须在引入jQuery后面写 #}
        <script src="/static/jquery.cookie.js"></script>
    
        <script>
            $(function(){
    {#            {'path': "/user_list/`"});加入这个就,就能使得对当前url有影响,其他的不影响#}
                    var v = $.cookie('per_page_count', {'path': "/user_list/`"});
                    $('#ps').val(v);
            });
    
            function changePageSize(ths){
                var v = $(ths).val();
                console.log(v);
                $.cookie('per_page_count',v, {'path': "/user_list/"});
    
                location.reload();
            }
    {#        $(function () {#}
    {#           var v = $.cookie('per_page_count');#}
    {#            var v = document.cookie('per_page_count');#}
    {#            $('#s1').val(v);#}
    {#        });#}
    {##}
    {#        function changePageSize(ths) {#}
    {#            var v = $(ths).val();#}
    {#            var v = $('#s1').val();#}
    {#            console.log(v);#}
    {#            $.cookie('per_page_count',v);#}
    {#            temp = 'per_page_count'+v +';';#}
    {#            console.log(temp);#}
    {#            document.cookie = temp;#}
    {##}
    {#            刷新#}
    {#            location.reload();#}
    {#        }#}
        </script>
    
    
    
    </body>
    </html>
    user_list.html(cookie影响分页)
    from django.shortcuts import render,HttpResponse
    from django.shortcuts import redirect
    from django.utils.safestring import mark_safe
    
    from app01 import models
    from utils import pagination
    import json
    # Create your views here.
    
    def business(request):
    
        # 获取数据,保存为queryset列表
        v = models.Business.objects.all()
    
        # 查找特定的列,类似select id,caption from business,返回的是字典
        v2 = models.Business.objects.all().values('id','caption')
    
        # 查询获取的结果,返回的是元组
        v3 = models.Business.objects.all().values_list('id','caption')
    
    
        return render(request,'business.html',{'v':v,"v2":v2,"v3":v3})
    
    
    def host(request):
        if request.method == "GET":
            v = models.Business.objects.filter(host__nid__gt=0)
            # # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为字典类型
            # v2 = models.Business.objects.all().values('nid', 'hostname', 'b__id', 'b__caption')
            # print(type(v2))
            # for row in v2:
            #     print(row['nid'], row['hostname'], row['b_id'], row['b__caption'])
    
            # # 因为引号里面是字符串,所以使用双下杠__引用对应对象下的字段,得到结果为元组,下标安装下方的写的参数从0排序+1
            # v3 = models.Business.objects.all().values_list('nid', 'hostname', 'b_id', 'b__caption')
            # print(type(v3))
    
            b_list = models.Host.objects.all()
            for row in b_list:
                print(row.hostname)
    
            return render(request, 'host.html', {"v": v,'b_list':b_list})
        # return render(request,'host.html',{"v":v,"v2":v2,"v3":v3})
    
        elif request.method == 'POST':
            h = request.POST.get('hostname')
            i = request.POST.get('ip')
            p = request.POST.get('port')
            b = request.POST.get('b_id')
            print(h)
            print(i)
            print(p)
            print(b)
    
            models.Host.objects.create(hostname = h,
                                       ip = i,
                                       port = p,
                                       b_id = b
                                       )
    
            return redirect('/host/')
    
    
    def test_ajax(request):
        # request.GET.get('pwd',sep='	')获取pwd的值,并且隔开
        # print(request.method,request.GET.get('user'),request.GET.get('pwd',sep='	'))
    
        ret = {'status': True, 'error': None, 'data': None}
        try:
    
            h = request.POST.get('hostname')
            i = request.POST.get('ip')
            p = request.POST.get('port')
            b = request.POST.get('b_id')
            print(h)
            print(i)
            print(p)
            print(b)
            if h and len(h) > 5:
                models.Host.objects.create(hostname=h,
                                           ip=i,
                                           port=p,
                                           b_id=b
                                           )
    
            else:
                ret['status'] = False
                ret['error'] = '太短了'
    
    
        except Exception as e:
            ret['status'] = False
            ret['error'] = '请求错误'
        return HttpResponse(json.dumps(ret))
    
    
    def app(request):
        if request.method == 'GET':
            app_list = models.Application.objects.all()
            for row in app_list:
                print(row.name,row.r.all())
    
            host_list = models.Host.objects.all()
            return render(request,'app.html',{'app_list':app_list,'host_list':host_list})
        elif request.method == 'POST':
            app_name = request.POST.get('app_name')
            host_list = request.POST.getlist('host_list')
            print(app_name,host_list)
    
            obj = models.Application.objects.create(name = app_name)
            obj.r.add(*host_list)
    
            return redirect('/app/')
    
    def ajax_add_app(request):
        ret = {'status':True,'error':None,"data":None}
        app_name = request.POST.get('app_name')
        host_list =request.POST.getlist('host_list')
        obj = models.Application.objects.create(name=app_name)
        obj.r.add(*host_list)
    
    
    
        return HttpResponse(json.dumps(ret))
    
    
    
    
    LIST = []
    for i in range(500):
        LIST.append(i)
    
    # def user_list(request):
    #     #  当前页,获取p的值,若没有值的时候,默认为1
    #     current_page = request.GET.get('p',1)
    #     # 传递过来的是字符串,这边是数字计算的
    #     current_page = int(current_page)
    #     start = (current_page-1) * 10
    #     end = current_page * 10
    #
    #     li = LIST[start:end]
    #
    #     all_count = len(LIST)
    #     # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
    #     count,y = divmod(all_count,10)
    #     # 如果有余数,分页数需要+1
    #     if y:
    #         count +=1
    #
    #     page_list = []
    #     for i in range(1,count+1):
    #         # 如果i等于当前页。将当前页颜色变一下
    #         if i == current_page:
    #             temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
    #         else:
    #             temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
    #         page_list.append(temp)
    #
    #     page_str = " ".join(page_list)
    #     page_str = mark_safe(page_str)
    #
    #     return render(request,'user_list.html',{'li':li,'page_str':page_str})
    # def user_list(request):
    #     '''
    #     特定为10页的时候
    #     :param request:
    #     :return:
    #     '''
    #     #  当前页,获取p的值,若没有值的时候,默认为1
    #     current_page = request.GET.get('p',1)
    #     # 传递过来的是字符串,这边是数字计算的
    #     current_page = int(current_page)
    #     start = (current_page-1) * 10
    #     end = current_page * 10
    #
    #     li = LIST[start:end]
    #
    #     all_count = len(LIST)
    #     # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
    #     total_count,y = divmod(all_count,10)
    #     # 如果有余数,分页数需要+1
    #     if y:
    #         total_count +=1
    #
    #     page_list = []
    #     # 显示页面当前页的前后五页
    #     # start_index = current_page - 5
    #     # end_index = current_page + 5 +1
    #     if total_count < 11:
    #         start_index = 0
    #         end_index = total_count
    #
    #     else:
    #         if current_page <= 6 :
    #             start_index = 1
    #             end_index = 11
    #         else:
    #             start_index = current_page - 5
    #             end_index = current_page +5 +1
    #             if (current_page + 5) > total_count:
    #                 start_index  = total_count - 11 +1
    #                 end_index = total_count +1
    #
    #
    #     for i in range(start_index,end_index):
    #         # 如果i等于当前页。将当前页颜色变一下
    #         if i == current_page:
    #             temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
    #         else:
    #             temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
    #         page_list.append(temp)
    #
    #     page_str = " ".join(page_list)
    #     page_str = mark_safe(page_str)
    #
    #     return render(request,'user_list.html',{'li':li,'page_str':page_str})
    # def user_list(request):
    #     '''
    #
    #     :param request:
    #     :return:
    #     '''
    #     #  当前页,获取p的值,若没有值的时候,默认为1
    #     current_page = request.GET.get('p',1)
    #     # 传递过来的是字符串,这边是数字计算的
    #     current_page = int(current_page)
    #     start = (current_page-1) * 10
    #     end = current_page * 10
    #
    #     li = LIST[start:end]
    #
    #     all_count = len(LIST)
    #     # divmod方法是除以多少余多少,这里是除以10,余多少。y为余数
    #     total_count,y = divmod(all_count,10)
    #     # 如果有余数,分页数需要+1
    #     if y:
    #         total_count +=1
    #
    #     page_list = []
    #     # 显示页码多少个,这里是11,建议使用基数
    #     perpage_num = 11
    #     # 显示页面当前页的前后五页
    #     # start_index = current_page - 5
    #     # end_index = current_page + 5 +1
    #     if total_count < perpage_num:
    #         start_index = 0
    #         end_index = total_count
    #
    #     else:
    #         if current_page <= (perpage_num+1)/2 :
    #             start_index = 1
    #             end_index = perpage_num
    #         else:
    #             start_index = current_page - (perpage_num-1)/2
    #             end_index = current_page +(perpage_num-1)/2 +1
    #             if (current_page + (perpage_num-1)/2) > total_count:
    #                 start_index  = total_count - perpage_num +1
    #                 end_index = total_count +1
    #     if current_page ==1:
    #         # javascript:void(0);这个代表什么都不干
    #         prev = '<a class="page active"  href="javascript:void(0);">上一页</a>'
    #     else:
    #         prev = '<a class="page active"  href="/user_list/?p=%s">上一页</a>' %(current_page-1)
    #     page_list.append(prev)
    #
    #     for i in range(int(start_index),int(end_index)):
    #         # 如果i等于当前页。将当前页颜色变一下
    #         if i == current_page:
    #             temp = '<a class="page active"  href="/user_list/?p=%s">%s</a>' %(i,i)
    #         else:
    #             temp = '<a class="page" href="/user_list/?p=%s">%s</a>' %(i,i)
    #         page_list.append(temp)
    #     if current_page == total_count:
    #         nex = '<a class="page active"  href="javascript:void(0)">下一页</a>'
    #     else:
    #         nex = '<a class="page active"  href="/user_list/?p=%s">下一页</a>' % (current_page + 1)
    #     page_list.append(nex)
    #     # 跳转
    #     jump = '''
    #     <input type = 'text'/><a onclick='jumpTo(this,"/user_list/?p=");'id='ii1'>GO</a>
    #     <script>
    #         function jumpTo(ths,base){
    #             var val = ths.previousSibling.value;
    #             location.href = base + val;
    #         }
    #     </script>
    #
    #     '''
    #     page_list.append(jump)
    #
    #     page_str = " ".join(page_list)
    #     page_str = mark_safe(page_str)
    
        # return render(request,'user_list.html',{'li':li,'page_str':page_str})
    
    def user_list(request):
        current_page = request.GET.get('p', 1)
        current_page = int(current_page)
    
        val = request.COOKIES.get('per_page_count')
        print(val)
        page_obj = pagination.Page(current_page, len(LIST),val)
        data = LIST[page_obj.start:page_obj.end]
        page_str = page_obj.page_str("/user_list/")
        # data = [4,5,6]
        # page_str = [1,2,3]
        return render(request, 'user_list.html', {'li': data, 'page_str': page_str})
    
    user_info = {
        'user':{"pwd":"123"}
    }
    def index(request):
        # 获取当前已经登陆的用户信息
        v = request.COOKIES.get('user111')
        if not v:
            return redirect('/login/')
    
        return render(request,'index.html',{'name':v})
    
    def login(request):
        if request.method == 'GET':
            return render(request,'login.html')
        elif request.method == 'POST':
            u = request.POST.get('user')
            p = request.POST.get('pwd')
            dic = user_info.get(u)
            if not dic:
                return render(request,'login.html')
            if dic['pwd'] == p:
                res = redirect('/index/')
                # 设定cookie user 为u
                res.set_cookie('user111',u)
                res.set_cookie('key','value')
                return res
            else:
                return render(request,'login.html')
    views.py

    带签名的cookie

     基于cookie做用户验证时,不适合存放敏感信息,例如账号密码,银行余额等

    优点:存储数据的压力放到客户端上

    FVB与MVB装饰器实现用户认证

    def auth(func):
        '''
        装饰器,如果发现cookie存储的不是用户名,则需要用户登录
        :param func:
        :return:
        '''
        def inner(request,*args,**kwargs):
            # 获取当前已经登陆的用户信息
            v = request.COOKIES.get('user111')
            if not v:
                return redirect('login')
            return func(request,*args,**kwargs)
        return inner
    
    @auth
    def index(request):
        # 获取当前已经登陆的用户信息,因为写了装饰器,所以不需要了
        v = request.COOKIES.get('user111')
        if not v:
            return redirect('/login/')
    
        return render(request,'index.html',{'name':v})
    FVB装饰器
    CBV
    def auth(func):
        '''
        装饰器,如果发现cookie存储的不是用户名,则需要用户登录
        :param func:
        :return:
        '''
        def inner(request,*args,**kwargs):
            # 获取当前已经登陆的用户信息
            v = request.COOKIES.get('user111')
            if not v:
                return redirect('login')
            return func(request,*args,**kwargs)
        return inner
    
    
    
    from django import views
    from django.utils.decorators import method_decorator
    
    # 在类上面写上这个@method_decorator(auth,name="dispatch")。相当于,在下写了第一个继承的函数
    @method_decorator(auth,name="dispatch")
    class Order(views.View):
        
        # 这里写一个之后,因为所有函数都先执行dispatch的,所以就类里面的所有函数都需要验证
        @method_decorator(auth)
        def dispatch(self, request, *args, **kwargs):
            return super(Order,self).dispatch(request, *args, **kwargs)
    
        # 写在方法上,是单独对这个方法使用验证
        @method_decorator(auth)
        def get(self,request):
            # 获取当前已经登陆的用户信息
            v = request.COOKIES.get('user111')
    
            return render(request, 'index.html', {'name': v})
        def post(self,request):
            # 获取当前已经登陆的用户信息
            v = request.COOKIES.get('user111')
            return render(request, 'index.html', {'name': v})
    装饰器

    session

      cookie是保存在用户浏览器端的键值对

      session是保存在服务器端的键值对

       session依赖于cookie

    注意:使用session之前,必须要进入到对应目录下执行代码

    python manage.py makemigrations

    python manage.py migrate

    session的id默认情况下Django的放在数据库里面的

    session默认存在两周

    建立session:

    # 生成随机字符串
    # 写到用户浏览器cookie
    # 保存到session中
    # 在随机字符串对应的字典中设置相关内容
    request.session['username'] = user    #设置session
    request.session['username']        #获取session

    服务器session
      request.session.get('username',None)  #获取session,如果不存在,默认设置为None
      request.session.clear           #用于注销,删除当前cookie
    在配置文件中设置默认操作,放在settings.py
        SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)
         
        SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
        SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
        SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
        SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
        SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)
        SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)
        SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
        SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)
    
    
    from django.shortcuts import render,redirect,HttpResponse
    
    # Create your views here.
    
    def login(request):
        if request.method == 'GET':
            return render(request,'login.html')
    
        elif request.method == "POST":
            user = request.POST.get('user')
            pwd = request.POST.get('pwd')
            if user == 'root' and pwd == '123':
                # 生成随机字符串
                # 写到用户浏览器cookie
                # 保存到session中
                # 在随机字符串对应的字典中设置相关内容
                request.session['username'] = user
                request.session['is_login'] = True
                return  redirect('/index/')
    
            else:
                return render(request, 'login.html')
    
    
    def index(request):
        # 获取当前用户的随机字符串
        # 根据随机字符串获取对应的信息
        if request.session['is_login']:
            return HttpResponse(request.session['username'])
        else:
            return HttpResponse('gun')
    views.py

    session类型

    python manage.py makemigrations
    
    python manage.py migrateDjango默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
     
    a. 配置 settings.py
     
        SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)
         
        SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
        SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
        SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
        SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
        SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)
        SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)
        SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
        SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)
     
     
     
    b. 使用
     
        def index(request):
            # 获取、设置、删除Session中数据
            request.session['k1']
            request.session.get('k1',None)
            request.session['k1'] = 123
            request.session.setdefault('k1',123) # 存在则不设置
            del request.session['k1']    #删除单个session
    
        request.session.clear (request.session.session_key)    #用于注销
     
            # 所有 键、值、键值对
            request.session.keys()
            request.session.values()
            request.session.items()
            request.session.iterkeys()
            request.session.itervalues()
            request.session.iteritems()
     
     
            # 用户session的随机字符串
            request.session.session_key
     
            # 将所有Session失效日期小于当前日期的数据删除
            request.session.clear_expired()
     
            # 检查 用户session的随机字符串 在数据库中是否
            request.session.exists("session_key")
     
            # 删除当前用户的所有Session数据
            request.session.delete("session_key")
     
            request.session.set_expiry(value)
                * 如果value是个整数,session会在些秒数后失效。
                * 如果value是个datatime或timedelta,session就会在这个时间后失效。
                * 如果value是0,用户关闭浏览器session就会失效。
                * 如果value是None,session会依赖全局session失效策略。
    数据库session
    Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
     a. 配置 settings.py
     
        SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
        SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
     
     
        SESSION_COOKIE_NAME = "sessionid"                        # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
        SESSION_COOKIE_PATH = "/"                                # Session的cookie保存的路径
        SESSION_COOKIE_DOMAIN = None                              # Session的cookie保存的域名
        SESSION_COOKIE_SECURE = False                             # 是否Https传输cookie
        SESSION_COOKIE_HTTPONLY = True                            # 是否Session的cookie只支持http传输
        SESSION_COOKIE_AGE = 1209600                              # Session的cookie失效日期(2周)
        SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # 是否关闭浏览器使得Session过期
        SESSION_SAVE_EVERY_REQUEST = False                        # 是否每次请求都保存Session,默认修改之后才保存
    缓存session
    a. 配置 settings.py
     
        SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
        SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T
     
     
        SESSION_COOKIE_NAME = "sessionid"                          # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
        SESSION_COOKIE_PATH = "/"                                  # Session的cookie保存的路径
        SESSION_COOKIE_DOMAIN = None                                # Session的cookie保存的域名
        SESSION_COOKIE_SECURE = False                               # 是否Https传输cookie
        SESSION_COOKIE_HTTPONLY = True                              # 是否Session的cookie只支持http传输
        SESSION_COOKIE_AGE = 1209600                                # Session的cookie失效日期(2周)
        SESSION_EXPIRE_AT_BROWSER_CLOSE = False                     # 是否关闭浏览器使得Session过期
        SESSION_SAVE_EVERY_REQUEST = False                          # 是否每次请求都保存Session,默认修改之后才保存
     
    文件session
     
    a. 配置 settings.py
     
        SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎
     
    缓存+数据库session
    a. 配置 settings.py
         
        SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎
     
    加密cookie session

    session验证码

    后续不上

    CSRF

    原理:第一次访问的时候,获取字符串,post请求的时候,将字符串带上发送过去

     对get请求没有限制,对post请求才有限制

    为了避免post请求的时候报403错误,需要再form表单里面加上{% csrf_token %}

     ajax请求的话,需要加上headers:{'X-CSRFtoken':$.cookie('csrftoken')},

    或者直接加上全局函数

    {#            全局变量,对函数内所有ajax有效#}
                $.ajaxSetup({
                    beforeSend:function (xhr,settings) {
    {#                    设置请求头#}
                        xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken'));
                    }
    
    
                 });
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/login/" method="post">
            <input type="text" name="user" />
            <input type="password" name="pwd" />
            <input type="checkbox" name="rmb" value="1" />3秒钟免登陆
            <input type="submit" value="提交"/>
            <input id="btn1" type="button" value="按钮1"/>
            <input id="btn2" type="button" value="按钮2"/>
            {%  csrf_token %}
        </form>
        <script src="/static/jquery-1.12.4.js"></script>
        <script src="/static/jquery.cookie.js"></script>
        <script>
            $(function () {
    {#            全局变量,对函数内所有ajax有效#}
                $.ajaxSetup({
                    beforeSend:function (xhr,settings) {
    {#                    设置请求头#}
                        xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken'));
                    }
    
    
                 });
                
                $('#btn1').click(function () {
    {#                var csrftoken = $.cookie('csrftoken');#}
                    $.ajax({
                        url:'/login/',
                        type:'POST',
                        data:{'user':'root','pwd':'123'},
    {#                    发送post请求的时候,需要加上才放置csrf阻止,由于上面$.ajaxSetup已经配置,所以不需要单独配置#}
    {#                    headers:{'X-CSRFtoken':$.cookie('csrftoken')},#}
                        success:function (data) {
                            console.log(1)
                        }
                    });
                     $('#btn2').click(function () {
    {#                var csrftoken = $.cookie('csrftoken');#}
                    $.ajax({
                        url:'/login/',
                        type:'POST',
                        data:{'user':'root','pwd':'123'},
    {#                    发送post请求的时候,需要加上才放置csrf阻止#}
    {#                    headers:{'X-CSRFtoken':$.cookie('csrftoken')},#}
                        success:function (data) {
                            console.log(2)
                        }
                    })
                })
            });
            })
    
        </script>
    </body>
    </html>
    login.html
    全局:
        settings.py里面的MIDDLEWARE下
      中间件 django.middleware.csrf.CsrfViewMiddleware
    
    局部:
    
    @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
    @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
    注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

    局部的例子如下

    中间件

    中间件拥有的函数(名字不能修改):

    class Row1(MiddlewareMixin):
        def process_request(self,request):
            print("row1_process_request")
    
        def process_response(self,request,response):
            print('row1_process_response')
            return response

     中间件的一般逻辑如下图

    Django1.10版本之前,若是遇到有return的process_request情况

    Django1.10版本后,若是遇到有return的process_request情

    中间件是在settings.py的MIDDLEWARE配置的,配置路径,到类

    from django.utils.deprecation import MiddlewareMixin
    
    class Row1(MiddlewareMixin):
        def process_request(self,request):
            print("row1_process_request")
    
        def process_response(self,request,response):
            print('row1_process_response')
            return response
    
    class Row2(MiddlewareMixin):
        def process_request(self,request):
            print("row2_process_request")
    
        def process_response(self,request,response):
            print('row2_process_response')
            return response
    
    class Row3(MiddlewareMixin):
        def process_request(self,request):
            print("row3_process_request")
    
        def process_response(self,request,response):
            print('row3_process_response')
            return response
    m1.py

    多了process_view

        def process_view(self,request,view_func,view_func_args,view_func_kwargs):
            '''
            :param request:
            :param view_func: 访问的时候对应views.py里面的函数
            :param view_func_args: views.py里面的函数的参数
            :param view_func_kwargs: views.py里面的函数的参数(字典)
            :return:
            '''
            print('row1_process_view')

    多了process_exception,若views.py里面对应的函数出现异常,会一个个中间件寻找能处理的异常函数,若没有,则页面报错,若存在,则返回对应的信息给前端

        def process_exception(self,request,exception):
            '''
            view里面对应的函数出现异常的时候执行
            :param exception: 对应异常
            :return:
            '''
            if isinstance(exception,ValueError):
                # 假设login函数出现异常,又没有处理,只需要这里返回信息,页面不会显示返回的信息
                print('row3_process_exception')
                return HttpResponse('出问题了')
    from django.utils.deprecation import MiddlewareMixin
    
    class Row1(MiddlewareMixin):
        def process_request(self,request):
            print("row1_process_request")
    
        def process_view(self,request,view_func,view_func_args,view_func_kwargs):
            '''
            :param request:
            :param view_func: 访问的时候对应views.py里面的函数
            :param view_func_args: views.py里面的函数的参数
            :param view_func_kwargs: views.py里面的函数的参数(字典)
            :return:
            '''
            print('row1_process_view')
    
        def process_response(self,request,response):
            print('row1_process_response')
            return response
    from django.shortcuts import HttpResponse
    
    class Row2(MiddlewareMixin):
        def process_request(self,request):
            print("row2_process_request")
            # return HttpResponse('走')
        def process_view(self, request, view_func, view_func_args, view_func_kwargs):
            print('row2_process_view')
    
        def process_response(self,request,response):
            print('row2_process_response')
            return response
    
    class Row3(MiddlewareMixin):
        def process_request(self,request):
            print("row3_process_request")
        def process_view(self,request,view_func,view_func_args,view_func_kwargs):
            print('row3_process_view')
    
        def process_response(self,request,response):
            print('row3_process_response')
            return response
    
        def process_exception(self,request,exception):
            '''
            view里面对应的函数出现异常的时候执行
            :param exception: 对应异常
            :return:
            '''
            if isinstance(exception,ValueError):
                # 假设login函数出现异常,又没有处理,只需要这里返回信息,页面不会显示返回的信息
                print('row3_process_exception')
                return HttpResponse('出问题了')
    m1.py
    from django.shortcuts import render,redirect,HttpResponse
    
    # Create your views here.
    def login(request):
        int('dsd')
        return render(request,'login.html')
    views.py

     缓存

     配置:

    # 此为开始调试用,实际内部不做任何操作
        # 配置:
            CACHES = {
                'default': {
                    'BACKEND': 'django.core.cache.backends.dummy.DummyCache',     # 引擎
                    'TIMEOUT': 300,                                               # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
                    'OPTIONS':{
                        'MAX_ENTRIES': 300,                                       # 最大缓存个数(默认300)
                        'CULL_FREQUENCY': 3,                                      # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
                    },
                    'KEY_PREFIX': '',                                             # 缓存key的前缀(默认空)
                    'VERSION': 1,                                                 # 缓存key的版本(默认1)
                    'KEY_FUNCTION' 函数名                                          # 生成key的函数(默认函数会生成为:【前缀:版本:key】)
                }
            }
    
    
        # 自定义key
        def default_key_func(key, key_prefix, version):
            """
            Default function to generate keys.
    
            Constructs the key used by all other methods. By default it prepends
            the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
            function with custom key making behavior.
            """
            return '%s:%s:%s' % (key_prefix, version, key)
    
        def get_key_func(key_func):
            """
            Function to decide which key function to use.
    
            Defaults to ``default_key_func``.
            """
            if key_func is not None:
                if callable(key_func):
                    return key_func
                else:
                    return import_string(key_func)
            return default_key_func
    1.开发调试
    # 此缓存将内容保存至内存的变量中
        # 配置:
            CACHES = {
                'default': {
                    'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
                    'LOCATION': 'unique-snowflake',
                }
            }
    
        # 注:其他配置同开发调试版本
    2.内存
    # 此缓存将内容保存至文件
        # 配置:
    
            CACHES = {
                'default': {
                    'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
                    'LOCATION': '/var/tmp/django_cache',
                }
            }
        # 注:其他配置同开发调试版本
    3.文件
    # 此缓存将内容保存至数据库
    
        # 配置:
            CACHES = {
                'default': {
                    'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
                    'LOCATION': 'my_cache_table', # 数据库表
                }
            }
    
        # 注:执行创建表命令 python manage.py createcachetable
    4.数据库
    # 此缓存使用python-memcached模块连接memcache
    
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
                'LOCATION': '127.0.0.1:11211',
            }
        }
    
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
                'LOCATION': 'unix:/tmp/memcached.sock',
            }
        }   
    
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
                'LOCATION': [
                    '172.19.26.240:11211',
                    '172.19.26.242:11211',
                ]
            }
        }
    5.Memcache缓存(python-memcached模块)
    # 此缓存使用pylibmc模块连接memcache
        
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
                'LOCATION': '127.0.0.1:11211',
            }
        }
    
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
                'LOCATION': '/tmp/memcached.sock',
            }
        }   
    
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
                'LOCATION': [
                    '172.19.26.240:11211',
                    '172.19.26.242:11211',
                ]
            }
        }
    6.Memcache缓存(pylibmc模块)
    CACHES = {
        "default": {
            "BACKEND": "django_redis.cache.RedisCache",
            "LOCATION": "redis://127.0.0.1:6379",
            "OPTIONS": {
                "CLIENT_CLASS": "django_redis.client.DefaultClient",
                "CONNECTION_POOL_KWARGS": {"max_connections": 100}
                # "PASSWORD": "密码",
            }
        }
    }
    7.Redis缓存(依赖:pip3 install django-redis)

    应用

    使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存
    
        MIDDLEWARE = [
    
        #这个中间件只有一个process_response,进来的时候不需要经过它
            'django.middleware.cache.UpdateCacheMiddleware',
            # 其他中间件...
    
        #这里只有process_view,出去的时候不需要经过
            'django.middleware.cache.FetchFromCacheMiddleware',
        ]
    
        CACHE_MIDDLEWARE_ALIAS = ""
        CACHE_MIDDLEWARE_SECONDS = ""
        CACHE_MIDDLEWARE_KEY_PREFIX = ""
    全局视图
    # 单视图,整个页面的缓存,设置为10秒,这里的优先级比默认的高
    from django.views.decorators.cache import cache_page
    @cache_page(10)
    def cache(request):
        import time
        ctime = time.time()
        return render(request,'cache.html',{'ctime':ctime})
    单视图缓存

    局部缓存在html写,需要导入

    {% load cache %}
    在需要缓存的地方上写,单位是秒,这里缓存10秒
    {% cache 10 c1 %}
    <h1>{{ ctime }}</h1>
    {% endcache %}
    {% load cache %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>{{ ctime }}</h1>
        <h1>{{ ctime }}</h1>
        {% cache 10 c1 %}
            <h1>{{ ctime }}</h1>
        {% endcache %}
    
    </body>
    </html>
    局部缓存.html

    信号

    (可以做日志)

    Model signals
        pre_init                    # django的modal执行其构造方法前,自动触发
        post_init                   # django的modal执行其构造方法后,自动触发
        pre_save                    # django的modal对象保存前,自动触发
        post_save                   # django的modal对象保存后,自动触发
        pre_delete                  # django的modal对象删除前,自动触发
        post_delete                 # django的modal对象删除后,自动触发
        m2m_changed                 # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
        class_prepared              # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
    Management signals
        pre_migrate                 # 执行migrate命令前,自动触发
        post_migrate                # 执行migrate命令后,自动触发
    Request/response signals
        request_started             # 请求到来前,自动触发
        request_finished            # 请求结束后,自动触发
        got_request_exception       # 请求异常后,自动触发
    Test signals
        setting_changed             # 使用test测试修改配置文件时,自动触发
        template_rendered           # 使用test测试渲染模板时,自动触发
    Database Wrappers
        connection_created          # 创建数据库连接时,自动触发
    Django内置信号

    对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:

    使用:

    from django.core.signals import request_finished
    from django.core.signals import request_started
    from django.core.signals import got_request_exception
    
    from django.db.models.signals import class_prepared
    from django.db.models.signals import pre_init, post_init
    from django.db.models.signals import pre_save, post_save
    from django.db.models.signals import pre_delete, post_delete
    from django.db.models.signals import m2m_changed
    from django.db.models.signals import pre_migrate, post_migrate
    
    from django.test.signals import setting_changed
    from django.test.signals import template_rendered
    
    from django.db.backends.signals import connection_created
    
    
    def callback(sender, **kwargs):
        print("xxoo_callback")
        print(sender,kwargs)
    
    # xxoo.connect(callback)
    # xxoo指上述导入的内容
    # 例如:
    pre_init.connect(callback)
    sg.py

    init.py导入sy.py

    from app01 import models
    def sigin(request):
        obj = models.UserInfo(username='root')
        print('end')
        obj.save()
        obj = models.UserInfo(username='root')
        obj.save()
    
        obj = models.UserInfo(username='root')
        obj.save()
    views.py

    自定义信号

    1.定义信号

    2.触发信号

    3.信号中注册函数

    sg.py加上这个

    import django.dispatch
    pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

    注册对应函数

    def callback(sender, **kwargs):
        print("callback")
        print(sender,kwargs)
     
    pizza_done.connect(callback)

    def sigin(request):
        from sg import pizza_done
        # sender随意些,后面的传递参数内容
        pizza_done.send(sender='sddsfs', toppings=123, size=456)
        return HttpResponse('ok')
    views.py

    form表单验证

    参考:http://www.cnblogs.com/wupeiqi/articles/6144178.html

    1.验证用户请求
    2.生成HTML标签,保留上一次填写的记录
    {{obj.user}}      

    3.显示错误信息{{ obj.errors.user.0 }}

    <p>{{ obj.user }}{{ obj.errors.user.0 }}</p>

     4.从数据库获取信息好返回到前端

    rom django import forms
    from django.forms import fields
    class FM(forms.Form):
        # 这里的变量与前端form里面的name一致才能获取对应的值
        # user = forms.CharField()
        # 可以自定义对应错误信息
        user = forms.CharField(error_messages={'required':'用户名不能为空。'})
    
        #  pwd = forms.CharField()
        pwd = forms.CharField(
            max_length=12,
            min_length=6,
            error_messages={'required':'密码不能为空。','min_length':'密码长度不能少于6','max_length':'密码长度不能大于12'}
        )
        # 单选下拉
        city1 = fields.ChoiceField(
            choices=[(0,'上海'),(1,'广州'),(2,'东莞')]
        )
        # 多选下拉
        city2 = fields.MultipleChoiceField(
            choices=[(0, '上海'), (1, '广州'), (2, '东莞')]
        )
    
        # email = forms.EmailField()
        email = forms.EmailField(error_messages={'required':'邮箱不能为空。','invalid':'邮箱格式错误'})
    
    def fm(request):
        if request.method == 'GET':
    
            # 从数据库中获取到数据
            dic = {
                'user':'root',
                'pwd':'123123',
                'email':'sada@111',
                'city1':1,
                'city2':[1,2]
            }
    
            # obj = FM()
            # 将获取到的数据传递到类FM
            obj = FM(initial=dic)
            return render(request,'fm.html',{'obj':obj})
        elif request.method == 'POST':
            # 获取用户所有数据
            # 每条数据请求的验证
            # 成功后,获取所有的正确的信息
            # 如果失败,显示错误信息
            # 这次请求是post里面的数据,所以传入request.POST
            obj = FM(request.POST)
            r1= obj.is_valid()
            print(r1)
            if r1:
                print(obj.cleaned_data)
    
            else:
                # obj.errors是字典
                print(obj.errors)
                print(obj.errors.as_json())
                print(obj.errors['user'])
                print(obj.errors['user'][0])
    
                return render(request,'fm.html',{'obj':obj})
    
            return redirect('/fm/')
    eg

     先导入对应forms,然后生成类

    from django import forms(不建议使用)
    from django.forms import fields(建议使用这个)
     
    from django import forms
    class FM(forms.Form):
        # 这里的变量与前端form里面的name一致才能获取对应的值
        # user = forms.CharField()
        # 可以自定义对应错误信息
        user = forms.CharField(error_messages={'required':'用户名不能为空。'})
    
        #  pwd = forms.CharField()
        pwd = forms.CharField(
            max_length=12,
            min_length=6,
            error_messages={'required':'密码不能为空。','min_length':'密码长度不能少于6','max_length':'密码长度不能大于12'}
        )
    
        # email = forms.EmailField()
        email = forms.EmailField(error_messages={'required':'邮箱不能为空。','invalid':'邮箱格式错误'})
    
    def fm(request):
        if request.method == 'GET':
            obj = FM()
            return render(request,'fm.html',{'obj':obj})
        elif request.method == 'POST':
            # 获取用户所有数据
            # 每条数据请求的验证
            # 成功后,获取所有的正确的信息
            # 如果失败,显示错误信息
            # 这次请求是post里面的数据,所以传入request.POST
            obj = FM(request.POST)
            r1= obj.is_valid()
            print(r1)
            if r1:
                print(obj.cleaned_data)
                # 这样就能创建用户对象了
                models.UserInfo.objects.create(**obj.cleaned_data)
            else:
                # obj.errors是字典
                print(obj.errors)
                print(obj.errors.as_json())
                print(obj.errors['user'])
                print(obj.errors['user'][0])
    
                return render(request,'fm.html',{'obj':obj})
    
            return redirect('/fm/')
    views.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/fm/" method="post">
            {% csrf_token %}
    {#        能自动生成标签,并且在新浏览器里面有特定的错误功能 ,建议使用这个,定制性比较好#}
            {{ obj.user }}
            <p>{{ obj.user }}{{ obj.errors.user.0 }}</p>
            <p>{{ obj.pwd }}{{ obj.errors.pwd.0 }}</p>
            <p>{{ obj.email }}{{ obj.errors.email.0 }}</p>
            <p><input type="submit" value="确定" />
    
    {#            *********************************#}
    {#        {{ obj.as_ul }}#}
    
    {#        ****************table需要加上table标签*****************#}
    {#        <table>#}
    {#            {{ obj.as_table }}#}
    {#         </table>#}
    {##}
    {#        *********************************#}
    {#        {{ obj.as_p }}#}
    
        </form>
    
    </body>
    </html>
    fm.html
    from django.shortcuts import render,redirect,HttpResponse
    
    # Create your views here.
    def login(request):
        int('dsd')
        return render(request,'login.html')
    # 单视图,整个页面的缓存,设置为10秒,这里的优先级比默认的高
    # from django.views.decorators.cache import cache_page
    # @cache_page(10)
    def cache(request):
        import time
        ctime = time.time()
        return render(request,'cache.html',{'ctime':ctime})
    
    from app01 import models
    def sigin(request):
        from sg import pizza_done
        # sender随意些,后面的传递参数内容
        pizza_done.send(sender='sddsfs', toppings=123, size=456)
    
    
    
        obj = models.UserInfo(username='root')
        print('end')
        obj.save()
        obj = models.UserInfo(username='root')
        obj.save()
    
        obj = models.UserInfo(username='root')
        obj.save()
        return  HttpResponse('ok')
    
    
    
    from django import forms
    # 多行文本导入,插件
    from django.forms import widgets
    # 建议将forms改为fields
    from django.forms import fields
    class FM(forms.Form):
        # 这里的变量与前端form里面的name一致才能获取对应的值
        # user = forms.CharField()
        # 可以自定义对应错误信息
        # 字段本身只做验证
        user = fields.CharField(error_messages={'required':'用户名不能为空。'})
    
        #  pwd = forms.CharField()
        pwd = fields.CharField(
            max_length=12,
            min_length=6,
            error_messages={'required':'密码不能为空。','min_length':'密码长度不能少于6','max_length':'密码长度不能大于12'},
            # 密码框
            # widget = widgets.PasswordInput
            # 如果想定制样式
            widget = widgets.PasswordInput(attrs={'class':'c2'})
        )
    
        # email = forms.EmailField()
        email = fields.EmailField(error_messages={'required':'邮箱不能为空。','invalid':'邮箱格式错误'})
        text1 = fields.CharField(
            # attrs={'class':'c1'}定义样式为c1
            widget = widgets.Textarea(attrs={'class':'c1'})
        )
    
    def fm(request):
        if request.method == 'GET':
            obj = FM()
            return render(request,'fm.html',{'obj':obj})
        elif request.method == 'POST':
            # 获取用户所有数据
            # 每条数据请求的验证
            # 成功后,获取所有的正确的信息
            # 如果失败,显示错误信息
            # 这次请求是post里面的数据,所以传入request.POST
            obj = FM(request.POST)
            r1= obj.is_valid()
            print(r1)
            if r1:
                print(obj.cleaned_data)
                # 这样就能创建用户对象了
                models.UserInfo.objects.create(**obj.cleaned_data)
            else:
                # obj.errors是字典
                print(obj.errors)
                print(obj.errors.as_json())
                print(obj.errors['user'])
                print(obj.errors['user'][0])
    
                return render(request,'fm.html',{'obj':obj})
    
            return redirect('/fm/')
    优化的views.py—1

    初始化操作:

      

    def fm(request):
        if request.method == 'GET':
    
            # 从数据库中获取到数据
            dic = {
                'user':'root',
                'pwd':'123123',
                'email':'sada@111',
                'city1':1,
                'city2':[1,2]
            }
    
            # obj = FM()
            # 将获取到的数据传递到类FM
            obj = FM(initial=dic)
            return render(request,'fm.html',{'obj':obj})

     modelform(耦合性太强,小的程序才用)

    参考:https://www.cnblogs.com/wupeiqi/articles/6229414.html

    # modelform方式
    class UserInfoModelForm(forms.ModelForm):
    
        class Meta:
            # 这里指定字段对应的表
            model  =models.UserInfo
            # __all__代表多有的字段
            fields = '__all__'
    
            # 只显示的字段
            # fields = ['username','email']
            # 排除字段,其他的显示
            exclude = ['email']
    # # modelform方式
    class UserInfoModelForm(forms.ModelForm):
    
        class Meta:
            # 这里指定字段对应的表
            model  =models.UserInfo
            # __all__代表多有的字段
            fields = '__all__'
    
            # 只显示的字段
            # fields = ['username','email']
            # 排除字段,其他的显示
            # exclude = ['email']
            # 显示标签更名
            labels = {
                'username':'用户名',
                'email':'邮箱'
            }
            #
            help_texts = {
                'username':'帮助信息'
            }
            # 将原来的CharField改为为Textarea
            widgets = {
                'username':Fwidgets.Textarea(attrs={'class':'c1'})
            }
            error_messages = {
                '__all__':'所有字段共同的错误',
                # email的错误信息
                'email':{
                    'required':'邮箱不能为空',
                    'invalid':'邮箱格式错误'
    
                }
            }
            # 更改格式,
            field_classes = {
                # 将email的格式从邮箱给为url格式,这里是填写类,不是带括号的对象
                'email': Ffields.URLField
            }
    views.py

    1.可以生产HTML标签:class Meta的参数

    2.页面显示带默认值,就需增加instance参数如:mf = xxxModelForm(instance = ModelObj)

    3.额外的标签:is_rmb = Ffields.CharField( widget=Fwidgets.CheckboxInput() )

    4.各种验证 is_valid() - > 各种钩子

    5.mf.save(),可以拆开

    instance = obj.save(False)
    instance.save()
    obj.save_m2m()
    from django.shortcuts import render
    from django import forms
    from django.forms import fields
    from django.forms import fields as Ffields
    from app01 import models
    # Create your views here.
    
    # 避免跟modelform的属性冲突,更名为Fwidgets
    from django.forms import widgets as Fwidgets
    # # modelform方式
    class UserInfoModelForm(forms.ModelForm):
    
        # 自定义字段,跟保存在数据库上没关系,例如一个月内免登陆的CheckBox
        is_rmb = Ffields.CharField(     widget=Fwidgets.CheckboxInput() )
    
        class Meta:
            # 这里指定字段对应的表
            model  =models.UserInfo
            # __all__代表多有的字段
            fields = '__all__'
    
            # 只显示的字段
            # fields = ['username','email']
            # 排除字段,其他的显示
            # exclude = ['email']
            # 显示标签更名
            labels = {
                'username':'用户名',
                'email':'邮箱'
            }
            #
            help_texts = {
                'username':'帮助信息'
            }
            # 将原来的CharField改为为Textarea
            widgets = {
                'username':Fwidgets.Textarea(attrs={'class':'c1'})
            }
            error_messages = {
                '__all__':'所有字段共同的错误',
                # email的错误信息
                'email':{
                    'required':'邮箱不能为空',
                    'invalid':'邮箱格式错误'
    
                }
            }
            # 更改格式,
            # field_classes = {
            #     # 将email的格式从邮箱给为url格式,这里是填写类,不是带括号的对象
            #     'email': Ffields.URLField
            # }
    
    # form方式
    class UserInfoForm(forms.Form):
        # 定义字段
        username = fields.CharField(max_length=32,label='用户名')
        email = fields.EmailField(label='邮件')
        # 将数据库的id caption字段作为下拉显示
        user_type = fields.ChoiceField(
            choices = models.UserType.objects.values_list('id','caption'),
            label='类型'
        )
        def __init__(self,*args,**kwargs):
            super(UserInfoForm,self).__init__(*args,**kwargs)
            # 这样子就能更新数据库不需要重启程序就能更新数据
            self.fields['user_type'].choices = models.UserType.objects.values_list('id','caption')
    
    def index(request):
    
        if request.method == 'GET':
    
            # 创建对象,会在前段自动生成对应的标签
            obj = UserInfoModelForm()
    
            return render(request,'index.html',{'obj':obj})
            # return render(request,'index.html')
        elif request.method == 'POST':
            # 创建对象,会在前段自动生成对应的标签
            obj = UserInfoModelForm(request.POST)
            if obj.is_valid():
                # obj.save()
                # 上面一句包含了下面三句代码,只不过默认传入commit=True
                instance = obj.save(False)
                instance.save()
                obj.save_m2m()
            # print(obj.is_valid())
            # print(obj.cleaned_data)
            # print(obj.errors)
            # obj.cleaned_data
    
            return render(request, 'index.html', {'obj': obj})
    
    
    
    def user_list(request):
    
        li = models.UserInfo.objects.all().select_related('user_type')
        return render(request,'user_list.html',{'li':li})
    
    
    def user_edit(request,nid):
        # 获取当前id对象的用户信息
        # 显示用户已经存在的数据
        if request.method == "GET":
            user_obj = models.UserInfo.objects.filter(id=nid).first()
            mf = UserInfoModelForm(instance=user_obj)
            return render(request,'user_edit.html',{'mf':mf,'nid':nid})
        elif request.method == 'POST':
            user_obj = models.UserInfo.objects.filter(id=nid).first()
            # instance=user_obj)告诉数据库要更新的是哪个对象
            mf = UserInfoModelForm(request.POST,instance=user_obj)
            if mf.is_valid():
                mf.save()
    
            else:
                print(mf.errors.as_json())
            return render(request, 'user_edit.html', {'mf': mf, 'nid': nid})
    views.py代码变成

    form

      UserInfoForm 继承Form,又继承BaseForm(方法所在)

    from django.shortcuts import render
    from django import forms
    from django.forms import fields
    from app01 import models
    # Create your views here.
    # # modelform方式
    # class UserInfoModelForm(forms.ModelForm):
    #
    #     class Meta:
    #         # 这里指定字段对应的表
    #         model  =models.UserInfo
    #         # __all__代表多有的字段
    #         fields = '__all__'
    #
    #         # 只显示的字段
    #         # fields = ['username','email']
    #         # 排除字段,其他的显示
    #         exclude = ['email']
    
    
    # form方式
    class UserInfoForm(forms.Form):
        # 定义字段
        username = fields.CharField(max_length=32,label='用户名')
        email = fields.EmailField(label='邮件')
        # 将数据库的id caption字段作为下拉显示
        user_type = fields.ChoiceField(
            choices = models.UserType.objects.values_list('id','caption'),
            label='类型'
        )
        def __init__(self,*args,**kwargs):
            super(UserInfoForm,self).__init__(*args,**kwargs)
            # 这样子就能更新数据库不需要重启程序就能更新数据
            self.fields['user_type'].choices = models.UserType.objects.values_list('id','caption')
    
    def index(request):
    
        if request.method == 'GET':
    
            # 创建对象,会在前段自动生成对应的标签
            obj = UserInfoForm()
    
            return render(request,'index.html',{'obj':obj})
            # return render(request,'index.html')
        elif request.method == 'POST':
            # 创建对象,会在前段自动生成对应的标签
            obj = UserInfoForm(request.POST)
            obj.is_valid()
                # obj.cleaned_data
    
            return render(request, 'index.html', {'obj': obj})
    views.py

     

    select_related()

    使用外键.出数据的情况,Django会导致请求数据库过多,例如,下面一个循环,就进行了11次请求,效率不高

    但是,如果后面加上select_related(),就会将表关联的数据一次拿出来了。当然,这样有所有的数据,所以会导致请求的数据过多,因此,可以增加对应的参数select_related('ut')

    prefetch_related

      users = models.User.objects.filter(id__gt=30).prefetch_related('ut') 会执行两次SQL请求

      # select * from users; where id > 30;

      # 获取上一步骤中所有的ut_id = [1,2]

      # select * from user_type where id in[1,2],所以下面就能直接从内存获取数据,而不需要再执行SQL请求

      for row in users:

        print(row.user,row.pwd,row.ut_id)

        print(row.ut.name)

    obj.full_clean()会对内容进行验证,若错误,则会抛出异常

     步骤:每个字段的正则验证

        clean钩子  

    可以利用继续的clean()方法,自定义错误

    kindEditor(视频132)

    参考:http://www.cnblogs.com/wupeiqi/articles/6307554.html 

    官网:http://kindeditor.net/demo.php

    初始化参数:http://kindeditor.net/docs/option.html

    组合查询

    开始的做法

    from django.shortcuts import render
    from app01 import models
    
    # Create your views here.
    
    
    def article(request,*args,**kwargs):
        # print(request.path_info)
        # from django.urls import reverse
        # # 反转获取url
        # url = reverse('article',kwargs=kwargs)
        # print(url)
        print(args)
        condition = {}
        for k,v in kwargs.items():
            kwargs[k] = int(v)
            # print(type(k))
            if v == '0':
                # print('什么都不做')
                pass
            else:
                condition[k] = v
    
        # {'article_type_id': '1', 'category_id': '0'}
        print(kwargs)
        article_type_list = models.ArticleType.objects.all()
        category_list = models.Category.objects.all()
    
        result = models.Article.objects.filter(**condition)
        return render(request,
                      'article.html',
                      {'result':result,
                       'article_type_list':article_type_list,
                       'category_list':category_list,
                       'arg_dict':kwargs
    
                       })
    views.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .condition a{
                display: inline-block;
                padding: 3px 5px;
                border: 1px solid #DDDDDD;
                margin: 5px;
            }
            .condition a.active{
                background-color: green;
            }
        </style>
    </head>
    <body>
        <h1>过滤条件</h1>
        <div class="condition">
            <div>
                {% if arg_dict.article_type_id == 0 %}
                     <a class="active" href="/article-0-{{ arg_dict.category_id }}/">全部</a>
                 {% else %}
                <a href="/article-0-{{ arg_dict.category_id }}/">全部</a>
                {% endif %}
                {% for row in article_type_list %}
                    {% if row.id == arg_dict.article_type_id %}
                        <a class="active" href="/article-{{ row.id }}-{{ arg_dict.category_id }}/">{{ row.caption }}</a>
                    {% else %}
                        <a href="/article-{{ row.id }}-{{ arg_dict.category_id }}/">{{ row.caption }}</a>
                    {% endif %}
                {% endfor %}
            </div>
    
              <div>
                  {% if arg_dict.category_id == 0 %}
                    <a class="active" href="/article-{{ arg_dict.article_type_id }}-0/">全部</a>
                      {% else %}
                    <a href="/article-{{ arg_dict.article_type_id }}-0/">全部</a>
                    {% endif %}
                {% for row in category_list %}
                    {% if row.id == arg_dict.category_id  %}
                        <a class="active" href="/article-{{ arg_dict.article_type_id }}-{{ row.id }}/">{{ row.caption }}</a>
                    {% else %}
                        <a href="/article-{{ arg_dict.article_type_id }}-{{ row.id }}/">{{ row.caption }}</a>
                    {% endif %}
                {% endfor %}
            </div>
        </div>
        <h1>查询结果</h1>
        <ul>
            {% for row in result %}
                    <li>{{ row.id }}-{{ row.title }}</li>
            {% endfor %}
        </ul>
    </body>
    </html>
    article.html

    优化:

    在app01建立新目录templatetags,建立任意.py文件,然后建立模板

    from django import template
    
    register = template.Library()
    
    # 注册成模板
    @register.simple_tag
    def filter_all():
    
        return '....'

    HTML文件头部写  {% load py文件名 %} 如:{% load filter %}

    输出:{% 函数名 %}  {% filter_all %}

    from django import template
    from django.utils.safestring import mark_safe
    register = template.Library()
    
    # 注册成模板
    @register.simple_tag
    def filter_all(arg_dict,k):
        '''
        因为内容以来于arg_dict,所以传递入参数
                {% if arg_dict.article_type_id == 0 %}
                     <a class="active" href="/article-0-{{ arg_dict.category_id }}/">全部</a>
                 {% else %}
                    <a href="/article-0-{{ arg_dict.category_id }}/">全部</a>
                {% endif %}
        :return:
        '''
        if k == 'article_type_id':
            n1 =arg_dict['article_type_id']
            n2=arg_dict['category_id']
            if n1 ==0:
                ret = '<a class="active" href="/article-0-%s/">全部</a>' % n2
            else:
                ret = '<a href="/article-0-%s/">全部</a>' % n2
    
        else:
            n1 = arg_dict['category_id']
            n2 = arg_dict['article_type_id']
            if n1 == 0:
                ret = '<a class="active" href="/article-%s-0/">全部</a>' % n2
            else:
                ret = '<a  href="/article-%s-0/">全部</a>' % n2
    
    
    
    
        # if arg_dict['article_type_id'] == 0:
        #     ret='<a class="active" href="/article-0-%s/">全部</a>'%(arg_dict['category_id'])
        # else:
        #     ret='<a  href="/article-0-%s/">全部</a>'%(arg_dict['category_id'])
    
        return mark_safe(ret)
    @register.simple_tag
    def filter_article_type(arg_dict,article_type_list):
        '''
        {% for row in article_type_list %}
            {% if row.id == arg_dict.article_type_id %}
                <a class="active" href="/article-{{ row.id }}-{{ arg_dict.category_id }}/">{{ row.caption }}</a>
            {% else %}
                <a href="/article-{{ row.id }}-{{ arg_dict.category_id }}/">{{ row.caption }}</a>
            {% endif %}
        {% endfor %}
        :return:
        '''
        ret = []
        for row in article_type_list:
            if row.id == arg_dict['article_type_id']:
                temp = '<a class="active" href="/article-%s-%s/">%s</a>' %(row.id,arg_dict['category_id'],row.caption)
            else:
                temp = '<a  href="/article-%s-%s/">%s</a>' %(row.id,arg_dict['category_id'],row.caption)
    
            ret.append(temp)
    
        return mark_safe(''.join(ret))
    
    # @register.simple_tag
    # def filter_article_type(arg_dict,article_type_list):
    #     '''
    #     {% for row in article_type_list %}
    #         {% if row.id == arg_dict.article_type_id %}
    #             <a class="active" href="/article-{{ row.id }}-{{ arg_dict.category_id }}/">{{ row.caption }}</a>
    #         {% else %}
    #             <a href="/article-{{ row.id }}-{{ arg_dict.category_id }}/">{{ row.caption }}</a>
    #         {% endif %}
    #     {% endfor %}
    #     :return:
    #     '''
    #     ret = []
    #     for row in article_type_list:
    #         if row.id == arg_dict['article_type_id']:
    #             temp = '<a class="active" href="/article-%s-%s/">%s</a>' %(row.id,arg_dict['category_id'],row.caption)
    #         else:
    #             temp = '<a  href="/article-%s-%s/">%s</a>' %(row.id,arg_dict['category_id'],row.caption)
    #
    #         ret.append(temp)
    #
    #     return mark_safe(''.join(ret))
    filter.py
    from django.shortcuts import render
    from app01 import models
    
    # Create your views here.
    
    
    def article(request,*args,**kwargs):
        # print(request.path_info)
        # from django.urls import reverse
        # # 反转获取url
        # url = reverse('article',kwargs=kwargs)
        # print(url)
        print(args)
        condition = {}
        for k,v in kwargs.items():
            kwargs[k] = int(v)
            # print(type(k))
            if v == '0':
                # print('什么都不做')
                pass
            else:
                condition[k] = v
    
        # {'article_type_id': '1', 'category_id': '0'}
        print(kwargs)
        article_type_list = models.ArticleType.objects.all()
        category_list = models.Category.objects.all()
    
        result = models.Article.objects.filter(**condition)
        return render(request,
                      'article.html',
                      {'result':result,
                       'article_type_list':article_type_list,
                       'category_list':category_list,
                       'arg_dict':kwargs
    
                       })
    views.py
    {% load filter %}
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .condition a{
                display: inline-block;
                padding: 3px 5px;
                border: 1px solid #DDDDDD;
                margin: 5px;
            }
            .condition a.active{
                background-color: green;
            }
        </style>
    </head>
    <body>
        <h1>过滤条件</h1>
        <div class="condition">
            <div>
                {% filter_all arg_dict 'article_type_id' %}
                {% filter_article_type arg_dict article_type_list %}
    {#            {% if arg_dict.article_type_id == 0 %}#}
    {#                 <a class="active" href="/article-0-{{ arg_dict.category_id }}/">全部</a>#}
    {#             {% else %}#}
    {#            <a href="/article-0-{{ arg_dict.category_id }}/">全部</a>#}
    {#            {% endif %}#}
    {#            {% for row in article_type_list %}#}
    {#                {% if row.id == arg_dict.article_type_id %}#}
    {#                    <a class="active" href="/article-{{ row.id }}-{{ arg_dict.category_id }}/">{{ row.caption }}</a>#}
    {#                {% else %}#}
    {#                    <a href="/article-{{ row.id }}-{{ arg_dict.category_id }}/">{{ row.caption }}</a>#}
    {#                {% endif %}#}
    {#            {% endfor %}#}
            </div>
    
              <div>
              {% filter_all arg_dict 'category_id' %}
    
    {#              {% if arg_dict.category_id == 0 %}#}
    {#                <a class="active" href="/article-{{ arg_dict.article_type_id }}-0/">全部</a>#}
    {#                  {% else %}#}
    {#                <a href="/article-{{ arg_dict.article_type_id }}-0/">全部</a>#}
    {#                {% endif %}#}
                {% for row in category_list %}
                    {% if row.id == arg_dict.category_id  %}
                        <a class="active" href="/article-{{ arg_dict.article_type_id }}-{{ row.id }}/">{{ row.caption }}</a>
                    {% else %}
                        <a href="/article-{{ arg_dict.article_type_id }}-{{ row.id }}/">{{ row.caption }}</a>
                    {% endif %}
                {% endfor %}
            </div>
        </div>
        <h1>查询结果</h1>
        <ul>
            {% for row in result %}
                    <li>{{ row.id }}-{{ row.title }}</li>
            {% endfor %}
        </ul>
    </body>
    </html>
    article.html

    JSONP

    是一种请求方式

    因为浏览器的同源策略(阻止Ajax请求,无法阻止<scritp src...>请求)

    巧妙:

      创建script标签

      src=远程地址

      返回的数据必须是js格式的

    只能发GET请求

    后续补充

    注意地方:

    1、写url的时候,建议增加结尾符合$,否则business_add地址永远无法执行

  • 相关阅读:
    # 2018-2019-1 20165206 《信息安全系统设计基础》第1周学习总结
    20165206 2017-2018-2《Java程序设计》课程总结
    2017-2018-2 20165206 实验五《网络编程与安全》实验报告
    20165206第4次实验《Android程序设计》实验报告
    同源策略、跨域解决方案
    盒子模型,块级元素和行内元素
    http常见错误
    深入理解 JavaScript 事件循环(一)— event loop
    git常用指令
    js 常用方法
  • 原文地址:https://www.cnblogs.com/cheng662540/p/9351284.html
Copyright © 2011-2022 走看看